1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/StaticPresData.h"
#include "gfxFontFeatures.h"
#include "mozilla/Preferences.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoUtils.h"
#include "mozilla/StaticPtr.h"
#include "nsPresContext.h"
namespace mozilla {
static StaticAutoPtr<StaticPresData> sSingleton;
void StaticPresData::Init() {
MOZ_ASSERT(!sSingleton);
sSingleton = new StaticPresData();
}
void StaticPresData::Shutdown() {
MOZ_ASSERT(sSingleton);
sSingleton = nullptr;
}
StaticPresData* StaticPresData::Get() {
MOZ_ASSERT(sSingleton);
return sSingleton;
}
StaticPresData::StaticPresData() {
mLangService = nsLanguageAtomService::GetService();
}
#define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
_pref.Assign(_s0); \
_pref.Append(_s1);
// clang-format off
static const char* const kGenericFont[] = {
".variable.",
".serif.",
".sans-serif.",
".monospace.",
".cursive.",
".fantasy.",
".system-ui.",
};
// clang-format on
enum class DefaultFont {
Variable = 0,
Serif,
SansSerif,
Monospace,
Cursive,
Fantasy,
SystemUi,
COUNT
};
void LangGroupFontPrefs::Initialize(nsStaticAtom* aLangGroupAtom) {
mLangGroup = aLangGroupAtom;
/* Fetch the font prefs to be used -- see bug 61883 for details.
Not all prefs are needed upfront. Some are fallback prefs intended
for the GFX font sub-system...
-- attributes for generic fonts --------------------------------------
font.default.[langGroup] = serif | sans-serif
fallback generic font
font.name.[generic].[langGroup]
current user' selected font on the pref dialog
font.name-list.[generic].[langGroup] = fontname1, fontname2, ...
[factory pre-built list]
font.size.[generic].[langGroup] = integer
settable by the user
font.size-adjust.[generic].[langGroup] = "float"
settable by the user
font.minimum-size.[langGroup] = integer
settable by the user
*/
nsAutoCString langGroup;
aLangGroupAtom->ToUTF8String(langGroup);
mDefaultVariableFont.size = Length::FromPixels(16.0f);
mDefaultMonospaceFont.size = Length::FromPixels(13.0f);
nsAutoCString pref;
// get font.minimum-size.[langGroup]
MAKE_FONT_PREF_KEY(pref, "font.minimum-size.", langGroup);
int32_t size = Preferences::GetInt(pref.get());
mMinimumFontSize = Length::FromPixels(size);
// clang-format off
nsFont* fontTypes[] = {
&mDefaultVariableFont,
&mDefaultSerifFont,
&mDefaultSansSerifFont,
&mDefaultMonospaceFont,
&mDefaultCursiveFont,
&mDefaultFantasyFont,
&mDefaultSystemUiFont,
};
// clang-format on
static_assert(std::size(fontTypes) == size_t(DefaultFont::COUNT),
"FontTypes array count is not correct");
// Get attributes specific to each generic font. We do not get the user's
// generic-font-name-to-specific-family-name preferences because its the
// generic name that should be fed into the cascade. It is up to the GFX
// code to look up the font prefs to convert generic names to specific
// family names as necessary.
nsAutoCString generic_dot_langGroup;
for (auto type : MakeEnumeratedRange(DefaultFont::COUNT)) {
generic_dot_langGroup.Assign(kGenericFont[size_t(type)]);
generic_dot_langGroup.Append(langGroup);
nsFont* font = fontTypes[size_t(type)];
// Set the default variable font (the other fonts are seen as 'generic'
// fonts in GFX and will be queried there when hunting for alternative
// fonts)
if (type == DefaultFont::Variable) {
// XXX "font.name.variable."? There is no such pref...
MAKE_FONT_PREF_KEY(pref, "font.name.variable.", langGroup);
nsAutoCString value;
Preferences::GetCString(pref.get(), value);
if (value.IsEmpty()) {
MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup);
Preferences::GetCString(pref.get(), value);
}
if (!value.IsEmpty()) {
auto defaultVariableName = StyleSingleFontFamily::Parse(value);
auto defaultType = defaultVariableName.IsGeneric()
? defaultVariableName.AsGeneric()
: StyleGenericFontFamily::None;
if (defaultType == StyleGenericFontFamily::Serif ||
defaultType == StyleGenericFontFamily::SansSerif) {
mDefaultVariableFont.family = *Servo_FontFamily_Generic(defaultType);
} else {
NS_WARNING("default type must be serif or sans-serif");
}
}
} else {
if (type != DefaultFont::Monospace) {
// all the other generic fonts are initialized with the size of the
// variable font, but their specific size can supersede later -- see
// below
font->size = mDefaultVariableFont.size;
}
}
// Bug 84398: for spec purists, a different font-size only applies to the
// .variable. and .fixed. fonts and the other fonts should get
// |font-size-adjust|. The problem is that only GfxWin has the support for
// |font-size-adjust|. So for parity, we enable the ability to set a
// different font-size on all platforms.
// get font.size.[generic].[langGroup]
// size=0 means 'Auto', i.e., generic fonts retain the size of the variable
// font
MAKE_FONT_PREF_KEY(pref, "font.size", generic_dot_langGroup);
size = Preferences::GetInt(pref.get());
if (size > 0) {
font->size = Length::FromPixels(size);
}
// get font.size-adjust.[generic].[langGroup]
// XXX only applicable on GFX ports that handle |font-size-adjust|
MAKE_FONT_PREF_KEY(pref, "font.size-adjust", generic_dot_langGroup);
nsAutoCString cvalue;
Preferences::GetCString(pref.get(), cvalue);
if (!cvalue.IsEmpty()) {
font->sizeAdjust =
StyleFontSizeAdjust::ExHeight(float(atof(cvalue.get())));
}
#ifdef DEBUG_rbs
printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
generic_dot_langGroup.get(), NS_ConvertUTF16toUTF8(font->name).get(),
font->size, font->sizeAdjust);
#endif
}
}
nsStaticAtom* StaticPresData::GetLangGroup(nsAtom* aLanguage) const {
nsStaticAtom* langGroupAtom = mLangService->GetLanguageGroup(aLanguage);
// Assume x-western is safe...
return langGroupAtom ? langGroupAtom : nsGkAtoms::x_western;
}
const LangGroupFontPrefs* StaticPresData::GetFontPrefsForLang(
nsAtom* aLanguage, bool* aNeedsToCache) {
// Get language group for aLanguage:
MOZ_ASSERT(aLanguage);
MOZ_ASSERT(mLangService);
nsStaticAtom* langGroupAtom = GetLangGroup(aLanguage);
if (!aNeedsToCache) {
AssertIsMainThreadOrServoFontMetricsLocked();
}
LangGroupFontPrefs* prefs = &mLangGroupFontPrefs;
if (prefs->mLangGroup) { // if initialized
DebugOnly<uint32_t> count = 0;
for (;;) {
if (prefs->mLangGroup == langGroupAtom) {
return prefs;
}
if (!prefs->mNext) {
break;
}
prefs = prefs->mNext.get();
}
if (aNeedsToCache) {
*aNeedsToCache = true;
return nullptr;
}
// nothing cached, so go on and fetch the prefs for this lang group:
prefs->mNext = MakeUnique<LangGroupFontPrefs>();
prefs = prefs->mNext.get();
}
if (aNeedsToCache) {
*aNeedsToCache = true;
return nullptr;
}
AssertIsMainThreadOrServoFontMetricsLocked();
prefs->Initialize(langGroupAtom);
return prefs;
}
} // namespace mozilla
|