diff options
Diffstat (limited to 'layout/base/StaticPresData.cpp')
-rw-r--r-- | layout/base/StaticPresData.cpp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/layout/base/StaticPresData.cpp b/layout/base/StaticPresData.cpp new file mode 100644 index 0000000000..6f92545b51 --- /dev/null +++ b/layout/base/StaticPresData.cpp @@ -0,0 +1,263 @@ +/* -*- 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(MOZ_ARRAY_LENGTH(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, + bool* aNeedsToCache) const { + nsStaticAtom* langGroupAtom = + mLangService->GetLanguageGroup(aLanguage, aNeedsToCache); + // Assume x-western is safe... + return langGroupAtom ? langGroupAtom : nsGkAtoms::x_western; +} + +nsStaticAtom* StaticPresData::GetUncachedLangGroup(nsAtom* aLanguage) const { + nsStaticAtom* langGroupAtom = + mLangService->GetUncachedLanguageGroup(aLanguage); + 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, aNeedsToCache); + if (aNeedsToCache && *aNeedsToCache) { + return nullptr; + } + + 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 |