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 "mozilla/Preferences.h"
10 #include "mozilla/ServoBindings.h"
11 #include "nsPresContext.h"
12 namespace mozilla {
13
14 static StaticPresData* sSingleton = nullptr;
15
Init()16 void StaticPresData::Init() {
17 MOZ_ASSERT(!sSingleton);
18 sSingleton = new StaticPresData();
19 }
20
Shutdown()21 void StaticPresData::Shutdown() {
22 MOZ_ASSERT(sSingleton);
23 delete sSingleton;
24 sSingleton = nullptr;
25 }
26
Get()27 StaticPresData* StaticPresData::Get() {
28 MOZ_ASSERT(sSingleton);
29 return sSingleton;
30 }
31
StaticPresData()32 StaticPresData::StaticPresData() {
33 mLangService = nsLanguageAtomService::GetService();
34
35 mBorderWidthTable[NS_STYLE_BORDER_WIDTH_THIN] =
36 nsPresContext::CSSPixelsToAppUnits(1);
37 mBorderWidthTable[NS_STYLE_BORDER_WIDTH_MEDIUM] =
38 nsPresContext::CSSPixelsToAppUnits(3);
39 mBorderWidthTable[NS_STYLE_BORDER_WIDTH_THICK] =
40 nsPresContext::CSSPixelsToAppUnits(5);
41 }
42
43 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
44 _pref.Assign(_s0); \
45 _pref.Append(_s1);
46
47 static const char* const kGenericFont[] = {
48 ".variable.", ".fixed.", ".serif.", ".sans-serif.",
49 ".monospace.", ".cursive.", ".fantasy."};
50
51 // These are private, use the list in nsFont.h if you want a public list.
52 enum {
53 eDefaultFont_Variable,
54 eDefaultFont_Fixed,
55 eDefaultFont_Serif,
56 eDefaultFont_SansSerif,
57 eDefaultFont_Monospace,
58 eDefaultFont_Cursive,
59 eDefaultFont_Fantasy,
60 eDefaultFont_COUNT
61 };
62
Initialize(nsAtom * aLangGroupAtom)63 void LangGroupFontPrefs::Initialize(nsAtom* aLangGroupAtom) {
64 mLangGroup = aLangGroupAtom;
65
66 /* Fetch the font prefs to be used -- see bug 61883 for details.
67 Not all prefs are needed upfront. Some are fallback prefs intended
68 for the GFX font sub-system...
69
70 -- attributes for generic fonts --------------------------------------
71 font.default.[langGroup] = serif | sans-serif - fallback generic font
72 font.name.[generic].[langGroup] = current user' selected font on the pref
73 dialog font.name-list.[generic].[langGroup] = fontname1, fontname2, ...
74 [factory pre-built list] font.size.[generic].[langGroup] = integer - settable
75 by the user font.size-adjust.[generic].[langGroup] = "float" - settable by the
76 user font.minimum-size.[langGroup] = integer - settable by the user
77 */
78
79 nsAutoCString langGroup;
80 aLangGroupAtom->ToUTF8String(langGroup);
81
82 mDefaultVariableFont.size = nsPresContext::CSSPixelsToAppUnits(16);
83 mDefaultFixedFont.size = nsPresContext::CSSPixelsToAppUnits(13);
84
85 nsAutoCString pref;
86
87 // get font.minimum-size.[langGroup]
88
89 MAKE_FONT_PREF_KEY(pref, "font.minimum-size.", langGroup);
90
91 int32_t size = Preferences::GetInt(pref.get());
92 mMinimumFontSize = nsPresContext::CSSPixelsToAppUnits(size);
93
94 nsFont* fontTypes[] = {&mDefaultVariableFont, &mDefaultFixedFont,
95 &mDefaultSerifFont, &mDefaultSansSerifFont,
96 &mDefaultMonospaceFont, &mDefaultCursiveFont,
97 &mDefaultFantasyFont};
98 static_assert(MOZ_ARRAY_LENGTH(fontTypes) == eDefaultFont_COUNT,
99 "FontTypes array count is not correct");
100
101 // Get attributes specific to each generic font. We do not get the user's
102 // generic-font-name-to-specific-family-name preferences because its the
103 // generic name that should be fed into the cascade. It is up to the GFX
104 // code to look up the font prefs to convert generic names to specific
105 // family names as necessary.
106 nsAutoCString generic_dot_langGroup;
107 for (uint32_t eType = 0; eType < ArrayLength(fontTypes); ++eType) {
108 generic_dot_langGroup.Assign(kGenericFont[eType]);
109 generic_dot_langGroup.Append(langGroup);
110
111 nsFont* font = fontTypes[eType];
112
113 // set the default variable font (the other fonts are seen as 'generic'
114 // fonts in GFX and will be queried there when hunting for alternative
115 // fonts)
116 if (eType == eDefaultFont_Variable) {
117 // XXX "font.name.variable."? There is no such pref...
118 MAKE_FONT_PREF_KEY(pref, "font.name.variable.", langGroup);
119
120 nsAutoString value;
121 Preferences::GetString(pref.get(), value);
122 if (!value.IsEmpty()) {
123 FontFamilyName defaultVariableName = FontFamilyName::Convert(value);
124 FontFamilyType defaultType = defaultVariableName.mType;
125 NS_ASSERTION(
126 defaultType == eFamily_serif || defaultType == eFamily_sans_serif,
127 "default type must be serif or sans-serif");
128 mDefaultVariableFont.fontlist = FontFamilyList();
129 mDefaultVariableFont.fontlist.SetDefaultFontType(defaultType);
130 // We create mDefaultVariableFont.fontlist with defaultType as the
131 // fallback font, and not as part of the font list proper. This way,
132 // it can be overwritten should there be a language change.
133 } else {
134 MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup);
135 Preferences::GetString(pref.get(), value);
136 if (!value.IsEmpty()) {
137 FontFamilyName defaultVariableName = FontFamilyName::Convert(value);
138 FontFamilyType defaultType = defaultVariableName.mType;
139 NS_ASSERTION(
140 defaultType == eFamily_serif || defaultType == eFamily_sans_serif,
141 "default type must be serif or sans-serif");
142 mDefaultVariableFont.fontlist = FontFamilyList();
143 mDefaultVariableFont.fontlist.SetDefaultFontType(defaultType);
144 // We create mDefaultVariableFont.fontlist with defaultType as the
145 // (fallback) font, and not as part of the font list proper. This way,
146 // it can be overwritten should there be a language change.
147 }
148 }
149 } else {
150 if (eType == eDefaultFont_Monospace) {
151 // This takes care of the confusion whereby people often expect
152 // "monospace" to have the same default font-size as "-moz-fixed" (this
153 // tentative size may be overwritten with the specific value for
154 // "monospace" when "font.size.monospace.[langGroup]" is read -- see
155 // below)
156 mDefaultMonospaceFont.size = mDefaultFixedFont.size;
157 } else if (eType != eDefaultFont_Fixed) {
158 // all the other generic fonts are initialized with the size of the
159 // variable font, but their specific size can supersede later -- see
160 // below
161 font->size = mDefaultVariableFont.size;
162 }
163 }
164
165 // Bug 84398: for spec purists, a different font-size only applies to the
166 // .variable. and .fixed. fonts and the other fonts should get
167 // |font-size-adjust|. The problem is that only GfxWin has the support for
168 // |font-size-adjust|. So for parity, we enable the ability to set a
169 // different font-size on all platforms.
170
171 // get font.size.[generic].[langGroup]
172 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable
173 // font
174 MAKE_FONT_PREF_KEY(pref, "font.size", generic_dot_langGroup);
175 size = Preferences::GetInt(pref.get());
176 if (size > 0) {
177 font->size = nsPresContext::CSSPixelsToAppUnits(size);
178 }
179
180 // get font.size-adjust.[generic].[langGroup]
181 // XXX only applicable on GFX ports that handle |font-size-adjust|
182 MAKE_FONT_PREF_KEY(pref, "font.size-adjust", generic_dot_langGroup);
183 nsAutoCString cvalue;
184 Preferences::GetCString(pref.get(), cvalue);
185 if (!cvalue.IsEmpty()) {
186 font->sizeAdjust = (float)atof(cvalue.get());
187 }
188
189 #ifdef DEBUG_rbs
190 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
191 generic_dot_langGroup.get(), NS_ConvertUTF16toUTF8(font->name).get(),
192 font->size, font->sizeAdjust);
193 #endif
194 }
195 }
196
GetLangGroup(nsAtom * aLanguage,bool * aNeedsToCache) const197 nsAtom* StaticPresData::GetLangGroup(nsAtom* aLanguage,
198 bool* aNeedsToCache) const {
199 nsAtom* langGroupAtom = nullptr;
200 langGroupAtom = mLangService->GetLanguageGroup(aLanguage, aNeedsToCache);
201 if (!langGroupAtom) {
202 langGroupAtom = nsGkAtoms::x_western; // Assume x-western is safe...
203 }
204 return langGroupAtom;
205 }
206
GetUncachedLangGroup(nsAtom * aLanguage) const207 already_AddRefed<nsAtom> StaticPresData::GetUncachedLangGroup(
208 nsAtom* aLanguage) const {
209 RefPtr<nsAtom> langGroupAtom =
210 mLangService->GetUncachedLanguageGroup(aLanguage);
211 if (!langGroupAtom) {
212 langGroupAtom = nsGkAtoms::x_western; // Assume x-western is safe...
213 }
214 return langGroupAtom.forget();
215 }
216
GetFontPrefsForLangHelper(nsAtom * aLanguage,const LangGroupFontPrefs * aPrefs,bool * aNeedsToCache) const217 const LangGroupFontPrefs* StaticPresData::GetFontPrefsForLangHelper(
218 nsAtom* aLanguage, const LangGroupFontPrefs* aPrefs,
219 bool* aNeedsToCache) const {
220 // Get language group for aLanguage:
221 MOZ_ASSERT(aLanguage);
222 MOZ_ASSERT(mLangService);
223 MOZ_ASSERT(aPrefs);
224
225 nsAtom* langGroupAtom = GetLangGroup(aLanguage, aNeedsToCache);
226
227 if (aNeedsToCache && *aNeedsToCache) {
228 return nullptr;
229 }
230
231 LangGroupFontPrefs* prefs = const_cast<LangGroupFontPrefs*>(aPrefs);
232 if (prefs->mLangGroup) { // if initialized
233 DebugOnly<uint32_t> count = 0;
234 for (;;) {
235 NS_ASSERTION(++count < 35, "Lang group count exceeded!!!");
236 if (prefs->mLangGroup == langGroupAtom) {
237 return prefs;
238 }
239 if (!prefs->mNext) {
240 break;
241 }
242 prefs = prefs->mNext;
243 }
244 if (aNeedsToCache) {
245 *aNeedsToCache = true;
246 return nullptr;
247 }
248 AssertIsMainThreadOrServoLangFontPrefsCacheLocked();
249 // nothing cached, so go on and fetch the prefs for this lang group:
250 prefs = prefs->mNext = new LangGroupFontPrefs;
251 }
252
253 if (aNeedsToCache) {
254 *aNeedsToCache = true;
255 return nullptr;
256 }
257
258 AssertIsMainThreadOrServoLangFontPrefsCacheLocked();
259 prefs->Initialize(langGroupAtom);
260
261 return prefs;
262 }
263
GetDefaultFontHelper(uint8_t aFontID,nsAtom * aLanguage,const LangGroupFontPrefs * aPrefs) const264 const nsFont* StaticPresData::GetDefaultFontHelper(
265 uint8_t aFontID, nsAtom* aLanguage,
266 const LangGroupFontPrefs* aPrefs) const {
267 MOZ_ASSERT(aLanguage);
268 MOZ_ASSERT(aPrefs);
269
270 const nsFont* font;
271 switch (aFontID) {
272 // Special (our default variable width font and fixed width font)
273 case kPresContext_DefaultVariableFont_ID:
274 font = &aPrefs->mDefaultVariableFont;
275 break;
276 case kPresContext_DefaultFixedFont_ID:
277 font = &aPrefs->mDefaultFixedFont;
278 break;
279 // CSS
280 case kGenericFont_serif:
281 font = &aPrefs->mDefaultSerifFont;
282 break;
283 case kGenericFont_sans_serif:
284 font = &aPrefs->mDefaultSansSerifFont;
285 break;
286 case kGenericFont_monospace:
287 font = &aPrefs->mDefaultMonospaceFont;
288 break;
289 case kGenericFont_cursive:
290 font = &aPrefs->mDefaultCursiveFont;
291 break;
292 case kGenericFont_fantasy:
293 font = &aPrefs->mDefaultFantasyFont;
294 break;
295 default:
296 font = nullptr;
297 NS_ERROR("invalid arg");
298 break;
299 }
300 return font;
301 }
302
303 } // namespace mozilla
304