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 "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"
18 static StaticAutoPtr
<StaticPresData
> sSingleton
;
20 void StaticPresData::Init() {
21 MOZ_ASSERT(!sSingleton
);
22 sSingleton
= new StaticPresData();
25 void StaticPresData::Shutdown() {
26 MOZ_ASSERT(sSingleton
);
30 StaticPresData
* StaticPresData::Get() {
31 MOZ_ASSERT(sSingleton
);
35 StaticPresData::StaticPresData() {
36 mLangService
= nsLanguageAtomService::GetService();
39 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
44 static const char* const kGenericFont
[] = {
55 enum class DefaultFont
{
66 void LangGroupFontPrefs::Initialize(nsStaticAtom
* aLangGroupAtom
) {
67 mLangGroup
= aLangGroupAtom
;
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...
73 -- attributes for generic fonts --------------------------------------
75 font.default.[langGroup] = serif | sans-serif
78 font.name.[generic].[langGroup]
79 current user' selected font on the pref dialog
81 font.name-list.[generic].[langGroup] = fontname1, fontname2, ...
82 [factory pre-built list]
84 font.size.[generic].[langGroup] = integer
87 font.size-adjust.[generic].[langGroup] = "float"
90 font.minimum-size.[langGroup] = integer
94 nsAutoCString langGroup
;
95 aLangGroupAtom
->ToUTF8String(langGroup
);
97 mDefaultVariableFont
.size
= Length::FromPixels(16.0f
);
98 mDefaultMonospaceFont
.size
= Length::FromPixels(13.0f
);
102 // get font.minimum-size.[langGroup]
104 MAKE_FONT_PREF_KEY(pref
, "font.minimum-size.", langGroup
);
106 int32_t size
= Preferences::GetInt(pref
.get());
107 mMinimumFontSize
= Length::FromPixels(size
);
110 nsFont
* fontTypes
[] = {
111 &mDefaultVariableFont
,
113 &mDefaultSansSerifFont
,
114 &mDefaultMonospaceFont
,
115 &mDefaultCursiveFont
,
116 &mDefaultFantasyFont
,
117 &mDefaultSystemUiFont
,
120 static_assert(std::size(fontTypes
) == size_t(DefaultFont::COUNT
),
121 "FontTypes array count is not correct");
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
);
133 nsFont
* font
= fontTypes
[size_t(type
)];
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
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
);
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
);
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
);
157 NS_WARNING("default type must be serif or sans-serif");
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
165 font
->size
= mDefaultVariableFont
.size
;
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.
175 // get font.size.[generic].[langGroup]
176 // size=0 means 'Auto', i.e., generic fonts retain the size of the variable
178 MAKE_FONT_PREF_KEY(pref
, "font.size", generic_dot_langGroup
);
179 size
= Preferences::GetInt(pref
.get());
181 font
->size
= Length::FromPixels(size
);
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()) {
191 StyleFontSizeAdjust::ExHeight(float(atof(cvalue
.get())));
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
);
202 nsStaticAtom
* StaticPresData::GetLangGroup(nsAtom
* aLanguage
,
203 bool* aNeedsToCache
) const {
204 nsStaticAtom
* langGroupAtom
=
205 mLangService
->GetLanguageGroup(aLanguage
, aNeedsToCache
);
206 // Assume x-western is safe...
207 return langGroupAtom
? langGroupAtom
: nsGkAtoms::x_western
;
210 nsStaticAtom
* StaticPresData::GetUncachedLangGroup(nsAtom
* aLanguage
) const {
211 nsStaticAtom
* langGroupAtom
=
212 mLangService
->GetUncachedLanguageGroup(aLanguage
);
213 return langGroupAtom
? langGroupAtom
: nsGkAtoms::x_western
;
216 const LangGroupFontPrefs
* StaticPresData::GetFontPrefsForLang(
217 nsAtom
* aLanguage
, bool* aNeedsToCache
) {
218 // Get language group for aLanguage:
219 MOZ_ASSERT(aLanguage
);
220 MOZ_ASSERT(mLangService
);
222 nsStaticAtom
* langGroupAtom
= GetLangGroup(aLanguage
, aNeedsToCache
);
223 if (aNeedsToCache
&& *aNeedsToCache
) {
227 if (!aNeedsToCache
) {
228 AssertIsMainThreadOrServoFontMetricsLocked();
231 LangGroupFontPrefs
* prefs
= &mLangGroupFontPrefs
;
232 if (prefs
->mLangGroup
) { // if initialized
233 DebugOnly
<uint32_t> count
= 0;
235 if (prefs
->mLangGroup
== langGroupAtom
) {
241 prefs
= prefs
->mNext
.get();
244 *aNeedsToCache
= true;
247 // nothing cached, so go on and fetch the prefs for this lang group:
248 prefs
->mNext
= MakeUnique
<LangGroupFontPrefs
>();
249 prefs
= prefs
->mNext
.get();
253 *aNeedsToCache
= true;
257 AssertIsMainThreadOrServoFontMetricsLocked();
258 prefs
->Initialize(langGroupAtom
);
263 } // namespace mozilla