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/. */
7 #include "mozilla/StaticPresData.h"
9 #include "mozilla/Preferences.h"
10 #include "mozilla/ServoBindings.h"
11 #include "mozilla/ServoUtils.h"
12 #include "nsPresContext.h"
16 static StaticPresData
* sSingleton
= nullptr;
18 void StaticPresData::Init() {
19 MOZ_ASSERT(!sSingleton
);
20 sSingleton
= new StaticPresData();
23 void StaticPresData::Shutdown() {
24 MOZ_ASSERT(sSingleton
);
29 StaticPresData
* StaticPresData::Get() {
30 MOZ_ASSERT(sSingleton
);
34 StaticPresData::StaticPresData() {
35 mLangService
= nsLanguageAtomService::GetService();
38 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
43 static const char* const kGenericFont
[] = {
53 // These are private, use the list in nsFont.h if you want a public list.
55 eDefaultFont_Variable
,
57 eDefaultFont_SansSerif
,
58 eDefaultFont_Monospace
,
64 void LangGroupFontPrefs::Initialize(nsStaticAtom
* aLangGroupAtom
) {
65 mLangGroup
= aLangGroupAtom
;
67 /* Fetch the font prefs to be used -- see bug 61883 for details.
68 Not all prefs are needed upfront. Some are fallback prefs intended
69 for the GFX font sub-system...
71 -- attributes for generic fonts --------------------------------------
73 font.default.[langGroup] = serif | sans-serif
76 font.name.[generic].[langGroup]
77 current user' selected font on the pref dialog
79 font.name-list.[generic].[langGroup] = fontname1, fontname2, ...
80 [factory pre-built list]
82 font.size.[generic].[langGroup] = integer
85 font.size-adjust.[generic].[langGroup] = "float"
88 font.minimum-size.[langGroup] = integer
92 nsAutoCString langGroup
;
93 aLangGroupAtom
->ToUTF8String(langGroup
);
95 mDefaultVariableFont
.size
= Length::FromPixels(16.0f
);
96 mDefaultMonospaceFont
.size
= Length::FromPixels(13.0f
);
100 // get font.minimum-size.[langGroup]
102 MAKE_FONT_PREF_KEY(pref
, "font.minimum-size.", langGroup
);
104 int32_t size
= Preferences::GetInt(pref
.get());
105 mMinimumFontSize
= Length::FromPixels(size
);
108 nsFont
* fontTypes
[] = {
109 &mDefaultVariableFont
,
111 &mDefaultSansSerifFont
,
112 &mDefaultMonospaceFont
,
113 &mDefaultCursiveFont
,
117 static_assert(MOZ_ARRAY_LENGTH(fontTypes
) == eDefaultFont_COUNT
,
118 "FontTypes array count is not correct");
120 // Get attributes specific to each generic font. We do not get the user's
121 // generic-font-name-to-specific-family-name preferences because its the
122 // generic name that should be fed into the cascade. It is up to the GFX
123 // code to look up the font prefs to convert generic names to specific
124 // family names as necessary.
125 nsAutoCString generic_dot_langGroup
;
126 for (uint32_t eType
= 0; eType
< ArrayLength(fontTypes
); ++eType
) {
127 generic_dot_langGroup
.Assign(kGenericFont
[eType
]);
128 generic_dot_langGroup
.Append(langGroup
);
130 nsFont
* font
= fontTypes
[eType
];
132 // set the default variable font (the other fonts are seen as 'generic'
133 // fonts in GFX and will be queried there when hunting for alternative
135 if (eType
== eDefaultFont_Variable
) {
136 // XXX "font.name.variable."? There is no such pref...
137 MAKE_FONT_PREF_KEY(pref
, "font.name.variable.", langGroup
);
140 Preferences::GetCString(pref
.get(), value
);
141 if (!value
.IsEmpty()) {
142 FontFamilyName defaultVariableName
= FontFamilyName::Convert(value
);
143 StyleGenericFontFamily defaultType
= defaultVariableName
.mGeneric
;
144 NS_ASSERTION(defaultType
== StyleGenericFontFamily::Serif
||
145 defaultType
== StyleGenericFontFamily::SansSerif
,
146 "default type must be serif or sans-serif");
147 mDefaultVariableFont
.fontlist
= FontFamilyList();
148 mDefaultVariableFont
.fontlist
.SetDefaultFontType(defaultType
);
149 // We create mDefaultVariableFont.fontlist with defaultType as the
150 // fallback font, and not as part of the font list proper. This way,
151 // it can be overwritten should there be a language change.
153 MAKE_FONT_PREF_KEY(pref
, "font.default.", langGroup
);
154 Preferences::GetCString(pref
.get(), value
);
155 if (!value
.IsEmpty()) {
156 FontFamilyName defaultVariableName
= FontFamilyName::Convert(value
);
157 StyleGenericFontFamily defaultType
= defaultVariableName
.mGeneric
;
158 NS_ASSERTION(defaultType
== StyleGenericFontFamily::Serif
||
159 defaultType
== StyleGenericFontFamily::SansSerif
,
160 "default type must be serif or sans-serif");
161 mDefaultVariableFont
.fontlist
= FontFamilyList();
162 mDefaultVariableFont
.fontlist
.SetDefaultFontType(defaultType
);
163 // We create mDefaultVariableFont.fontlist with defaultType as the
164 // (fallback) font, and not as part of the font list proper. This way,
165 // it can be overwritten should there be a language change.
169 if (eType
!= eDefaultFont_Monospace
) {
170 // all the other generic fonts are initialized with the size of the
171 // variable font, but their specific size can supersede later -- see
173 font
->size
= mDefaultVariableFont
.size
;
177 // Bug 84398: for spec purists, a different font-size only applies to the
178 // .variable. and .fixed. fonts and the other fonts should get
179 // |font-size-adjust|. The problem is that only GfxWin has the support for
180 // |font-size-adjust|. So for parity, we enable the ability to set a
181 // different font-size on all platforms.
183 // get font.size.[generic].[langGroup]
184 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable
186 MAKE_FONT_PREF_KEY(pref
, "font.size", generic_dot_langGroup
);
187 size
= Preferences::GetInt(pref
.get());
189 font
->size
= Length::FromPixels(size
);
192 // get font.size-adjust.[generic].[langGroup]
193 // XXX only applicable on GFX ports that handle |font-size-adjust|
194 MAKE_FONT_PREF_KEY(pref
, "font.size-adjust", generic_dot_langGroup
);
195 nsAutoCString cvalue
;
196 Preferences::GetCString(pref
.get(), cvalue
);
197 if (!cvalue
.IsEmpty()) {
198 font
->sizeAdjust
= (float)atof(cvalue
.get());
202 printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
203 generic_dot_langGroup
.get(), NS_ConvertUTF16toUTF8(font
->name
).get(),
204 font
->size
, font
->sizeAdjust
);
209 nsStaticAtom
* StaticPresData::GetLangGroup(nsAtom
* aLanguage
,
210 bool* aNeedsToCache
) const {
211 nsStaticAtom
* langGroupAtom
=
212 mLangService
->GetLanguageGroup(aLanguage
, aNeedsToCache
);
213 // Assume x-western is safe...
214 return langGroupAtom
? langGroupAtom
: nsGkAtoms::x_western
;
217 nsStaticAtom
* StaticPresData::GetUncachedLangGroup(nsAtom
* aLanguage
) const {
218 nsStaticAtom
* langGroupAtom
=
219 mLangService
->GetUncachedLanguageGroup(aLanguage
);
220 return langGroupAtom
? langGroupAtom
: nsGkAtoms::x_western
;
223 const LangGroupFontPrefs
* StaticPresData::GetFontPrefsForLang(
224 nsAtom
* aLanguage
, bool* aNeedsToCache
) {
225 // Get language group for aLanguage:
226 MOZ_ASSERT(aLanguage
);
227 MOZ_ASSERT(mLangService
);
229 nsStaticAtom
* langGroupAtom
= GetLangGroup(aLanguage
, aNeedsToCache
);
230 if (aNeedsToCache
&& *aNeedsToCache
) {
234 if (!aNeedsToCache
) {
235 AssertIsMainThreadOrServoFontMetricsLocked();
238 LangGroupFontPrefs
* prefs
= &mLangGroupFontPrefs
;
239 if (prefs
->mLangGroup
) { // if initialized
240 DebugOnly
<uint32_t> count
= 0;
242 if (prefs
->mLangGroup
== langGroupAtom
) {
248 prefs
= prefs
->mNext
.get();
251 *aNeedsToCache
= true;
254 // nothing cached, so go on and fetch the prefs for this lang group:
255 prefs
->mNext
= MakeUnique
<LangGroupFontPrefs
>();
256 prefs
= prefs
->mNext
.get();
260 *aNeedsToCache
= true;
264 AssertIsMainThreadOrServoFontMetricsLocked();
265 prefs
->Initialize(langGroupAtom
);
270 } // namespace mozilla