Bug 1709347 - Add CanvasRenderingContext2D.reset(). r=lsalzman,webidl,smaug
[gecko.git] / layout / base / StaticPresData.cpp
blob6f92545b510340f1ea693c52fec28d1a2dd6f562
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"
16 namespace mozilla {
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);
27 sSingleton = nullptr;
30 StaticPresData* StaticPresData::Get() {
31 MOZ_ASSERT(sSingleton);
32 return sSingleton;
35 StaticPresData::StaticPresData() {
36 mLangService = nsLanguageAtomService::GetService();
39 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
40 _pref.Assign(_s0); \
41 _pref.Append(_s1);
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.",
53 // clang-format on
55 enum class DefaultFont {
56 Variable = 0,
57 Serif,
58 SansSerif,
59 Monospace,
60 Cursive,
61 Fantasy,
62 SystemUi,
63 COUNT
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
76 fallback generic font
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
85 settable by the user
87 font.size-adjust.[generic].[langGroup] = "float"
88 settable by the user
90 font.minimum-size.[langGroup] = integer
91 settable by the user
94 nsAutoCString langGroup;
95 aLangGroupAtom->ToUTF8String(langGroup);
97 mDefaultVariableFont.size = Length::FromPixels(16.0f);
98 mDefaultMonospaceFont.size = Length::FromPixels(13.0f);
100 nsAutoCString pref;
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);
109 // clang-format off
110 nsFont* fontTypes[] = {
111 &mDefaultVariableFont,
112 &mDefaultSerifFont,
113 &mDefaultSansSerifFont,
114 &mDefaultMonospaceFont,
115 &mDefaultCursiveFont,
116 &mDefaultFantasyFont,
117 &mDefaultSystemUiFont,
119 // clang-format on
120 static_assert(MOZ_ARRAY_LENGTH(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
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);
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);
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");
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;
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
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);
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()));
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
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) {
224 return nullptr;
227 if (!aNeedsToCache) {
228 AssertIsMainThreadOrServoFontMetricsLocked();
231 LangGroupFontPrefs* prefs = &mLangGroupFontPrefs;
232 if (prefs->mLangGroup) { // if initialized
233 DebugOnly<uint32_t> count = 0;
234 for (;;) {
235 if (prefs->mLangGroup == langGroupAtom) {
236 return prefs;
238 if (!prefs->mNext) {
239 break;
241 prefs = prefs->mNext.get();
243 if (aNeedsToCache) {
244 *aNeedsToCache = true;
245 return nullptr;
247 // nothing cached, so go on and fetch the prefs for this lang group:
248 prefs->mNext = MakeUnique<LangGroupFontPrefs>();
249 prefs = prefs->mNext.get();
252 if (aNeedsToCache) {
253 *aNeedsToCache = true;
254 return nullptr;
257 AssertIsMainThreadOrServoFontMetricsLocked();
258 prefs->Initialize(langGroupAtom);
260 return prefs;
263 } // namespace mozilla