StaticPresData.cpp (7696B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/StaticPresData.h" 8 9 #include "gfxFontFeatures.h" 10 #include "mozilla/Preferences.h" 11 #include "mozilla/ServoBindings.h" 12 #include "mozilla/ServoUtils.h" 13 #include "mozilla/StaticPtr.h" 14 #include "nsPresContext.h" 15 16 namespace mozilla { 17 18 static StaticAutoPtr<StaticPresData> sSingleton; 19 20 void StaticPresData::Init() { 21 MOZ_ASSERT(!sSingleton); 22 sSingleton = new StaticPresData(); 23 } 24 25 void StaticPresData::Shutdown() { 26 MOZ_ASSERT(sSingleton); 27 sSingleton = nullptr; 28 } 29 30 StaticPresData* StaticPresData::Get() { 31 MOZ_ASSERT(sSingleton); 32 return sSingleton; 33 } 34 35 StaticPresData::StaticPresData() { 36 mLangService = nsLanguageAtomService::GetService(); 37 } 38 39 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \ 40 _pref.Assign(_s0); \ 41 _pref.Append(_s1); 42 43 // clang-format off 44 static const char* const kGenericFont[] = { 45 ".variable.", 46 ".serif.", 47 ".sans-serif.", 48 ".monospace.", 49 ".cursive.", 50 ".fantasy.", 51 ".system-ui.", 52 }; 53 // clang-format on 54 55 enum class DefaultFont { 56 Variable = 0, 57 Serif, 58 SansSerif, 59 Monospace, 60 Cursive, 61 Fantasy, 62 SystemUi, 63 COUNT 64 }; 65 66 void LangGroupFontPrefs::Initialize(nsStaticAtom* aLangGroupAtom) { 67 mLangGroup = aLangGroupAtom; 68 69 /* Fetch the font prefs to be used -- see bug 61883 for details. 70 Not all prefs are needed upfront. Some are fallback prefs intended 71 for the GFX font sub-system... 72 73 -- attributes for generic fonts -------------------------------------- 74 75 font.default.[langGroup] = serif | sans-serif 76 fallback generic font 77 78 font.name.[generic].[langGroup] 79 current user' selected font on the pref dialog 80 81 font.name-list.[generic].[langGroup] = fontname1, fontname2, ... 82 [factory pre-built list] 83 84 font.size.[generic].[langGroup] = integer 85 settable by the user 86 87 font.size-adjust.[generic].[langGroup] = "float" 88 settable by the user 89 90 font.minimum-size.[langGroup] = integer 91 settable by the user 92 */ 93 94 nsAutoCString langGroup; 95 aLangGroupAtom->ToUTF8String(langGroup); 96 97 mDefaultVariableFont.size = Length::FromPixels(16.0f); 98 mDefaultMonospaceFont.size = Length::FromPixels(13.0f); 99 100 nsAutoCString pref; 101 102 // get font.minimum-size.[langGroup] 103 104 MAKE_FONT_PREF_KEY(pref, "font.minimum-size.", langGroup); 105 106 int32_t size = Preferences::GetInt(pref.get()); 107 mMinimumFontSize = Length::FromPixels(size); 108 109 // clang-format off 110 nsFont* fontTypes[] = { 111 &mDefaultVariableFont, 112 &mDefaultSerifFont, 113 &mDefaultSansSerifFont, 114 &mDefaultMonospaceFont, 115 &mDefaultCursiveFont, 116 &mDefaultFantasyFont, 117 &mDefaultSystemUiFont, 118 }; 119 // clang-format on 120 static_assert(std::size(fontTypes) == size_t(DefaultFont::COUNT), 121 "FontTypes array count is not correct"); 122 123 // Get attributes specific to each generic font. We do not get the user's 124 // generic-font-name-to-specific-family-name preferences because its the 125 // generic name that should be fed into the cascade. It is up to the GFX 126 // code to look up the font prefs to convert generic names to specific 127 // family names as necessary. 128 nsAutoCString generic_dot_langGroup; 129 for (auto type : MakeEnumeratedRange(DefaultFont::COUNT)) { 130 generic_dot_langGroup.Assign(kGenericFont[size_t(type)]); 131 generic_dot_langGroup.Append(langGroup); 132 133 nsFont* font = fontTypes[size_t(type)]; 134 135 // Set the default variable font (the other fonts are seen as 'generic' 136 // fonts in GFX and will be queried there when hunting for alternative 137 // fonts) 138 if (type == DefaultFont::Variable) { 139 // XXX "font.name.variable."? There is no such pref... 140 MAKE_FONT_PREF_KEY(pref, "font.name.variable.", langGroup); 141 142 nsAutoCString value; 143 Preferences::GetCString(pref.get(), value); 144 if (value.IsEmpty()) { 145 MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup); 146 Preferences::GetCString(pref.get(), value); 147 } 148 if (!value.IsEmpty()) { 149 auto defaultVariableName = StyleSingleFontFamily::Parse(value); 150 auto defaultType = defaultVariableName.IsGeneric() 151 ? defaultVariableName.AsGeneric() 152 : StyleGenericFontFamily::None; 153 if (defaultType == StyleGenericFontFamily::Serif || 154 defaultType == StyleGenericFontFamily::SansSerif) { 155 mDefaultVariableFont.family = *Servo_FontFamily_Generic(defaultType); 156 } else { 157 NS_WARNING("default type must be serif or sans-serif"); 158 } 159 } 160 } else { 161 if (type != DefaultFont::Monospace) { 162 // all the other generic fonts are initialized with the size of the 163 // variable font, but their specific size can supersede later -- see 164 // below 165 font->size = mDefaultVariableFont.size; 166 } 167 } 168 169 // Bug 84398: for spec purists, a different font-size only applies to the 170 // .variable. and .fixed. fonts and the other fonts should get 171 // |font-size-adjust|. The problem is that only GfxWin has the support for 172 // |font-size-adjust|. So for parity, we enable the ability to set a 173 // different font-size on all platforms. 174 175 // get font.size.[generic].[langGroup] 176 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable 177 // font 178 MAKE_FONT_PREF_KEY(pref, "font.size", generic_dot_langGroup); 179 size = Preferences::GetInt(pref.get()); 180 if (size > 0) { 181 font->size = Length::FromPixels(size); 182 } 183 184 // get font.size-adjust.[generic].[langGroup] 185 // XXX only applicable on GFX ports that handle |font-size-adjust| 186 MAKE_FONT_PREF_KEY(pref, "font.size-adjust", generic_dot_langGroup); 187 nsAutoCString cvalue; 188 Preferences::GetCString(pref.get(), cvalue); 189 if (!cvalue.IsEmpty()) { 190 font->sizeAdjust = 191 StyleFontSizeAdjust::ExHeight(float(atof(cvalue.get()))); 192 } 193 194 #ifdef DEBUG_rbs 195 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n", 196 generic_dot_langGroup.get(), NS_ConvertUTF16toUTF8(font->name).get(), 197 font->size, font->sizeAdjust); 198 #endif 199 } 200 } 201 202 nsStaticAtom* StaticPresData::GetLangGroup(nsAtom* aLanguage) const { 203 nsStaticAtom* langGroupAtom = mLangService->GetLanguageGroup(aLanguage); 204 // Assume x-western is safe... 205 return langGroupAtom ? langGroupAtom : nsGkAtoms::x_western; 206 } 207 208 const LangGroupFontPrefs* StaticPresData::GetFontPrefsForLang( 209 nsAtom* aLanguage, bool* aNeedsToCache) { 210 // Get language group for aLanguage: 211 MOZ_ASSERT(aLanguage); 212 MOZ_ASSERT(mLangService); 213 214 nsStaticAtom* langGroupAtom = GetLangGroup(aLanguage); 215 216 if (!aNeedsToCache) { 217 AssertIsMainThreadOrServoFontMetricsLocked(); 218 } 219 220 LangGroupFontPrefs* prefs = &mLangGroupFontPrefs; 221 if (prefs->mLangGroup) { // if initialized 222 DebugOnly<uint32_t> count = 0; 223 for (;;) { 224 if (prefs->mLangGroup == langGroupAtom) { 225 return prefs; 226 } 227 if (!prefs->mNext) { 228 break; 229 } 230 prefs = prefs->mNext.get(); 231 } 232 if (aNeedsToCache) { 233 *aNeedsToCache = true; 234 return nullptr; 235 } 236 // nothing cached, so go on and fetch the prefs for this lang group: 237 prefs->mNext = MakeUnique<LangGroupFontPrefs>(); 238 prefs = prefs->mNext.get(); 239 } 240 241 if (aNeedsToCache) { 242 *aNeedsToCache = true; 243 return nullptr; 244 } 245 246 AssertIsMainThreadOrServoFontMetricsLocked(); 247 prefs->Initialize(langGroupAtom); 248 249 return prefs; 250 } 251 252 } // namespace mozilla