forked from mirrors/gecko-dev
		
	 ff07ef7e17
			
		
	
	
		ff07ef7e17
		
	
	
	
	
		
			
			.fallback is always the default font for the lang group unless we're a system font (in which case it's "none"). The only reason we need that is because we need to react to language changes (which affect the initial font). Simplify the model a bit doing the language lookup in gfxTextRun (this should avoid allocating a few nsStyleFont structs too. Depends on D130732 Differential Revision: https://phabricator.services.mozilla.com/D131312
		
			
				
	
	
		
			263 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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
 |