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