author Emilio Cobos Álvarez <>
Mon, 01 Apr 2019 18:48:10 +0000
changeset 467430 0cd1411e2fb32f57c3ed90914f5770932eff139f
parent 467006 7de6e431f1ae32cacc2b5d4aea1c47bf7900c4c4
child 467431 7375a830b5ef05e6d3049aed28b979f591a3dd12
permissions -rw-r--r--
Bug 1537575 - Cleanup generic font-family handling. r=jfkthame To be more similar between Rust and C++. This introduces GenericFontFamily and exposes that plus FontFamilyNameSyntax to C++, using that where appropriate instead of plain uint8_t as we were doing. As a follow-up, as discussed on IRC with Jonathan, we can remove the -moz-fixed family, and turn it just into an alias of Monospace. The only non-trivial change is the MatchType changes, but they're ok I think. The code already assumed at most one CSS generic, and the struct still takes 8 bits. I've verified that the relevant tests are passing (though try is closed). Differential Revision:

/* -*- 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 */

#ifndef mozilla_StaticPresData_h
#define mozilla_StaticPresData_h

#include "mozilla/UniquePtr.h"
#include "nsCoord.h"
#include "nsCOMPtr.h"
#include "nsFont.h"
#include "nsAtom.h"
#include "nsLanguageAtomService.h"

namespace mozilla {

struct LangGroupFontPrefs {
  // Font sizes default to zero; they will be set in GetFontPreferences
      : mLangGroup(nullptr),
        mDefaultFixedFont(StyleGenericFontFamily::MozFixed, 0),
        mDefaultSerifFont(StyleGenericFontFamily::Serif, 0),
        mDefaultSansSerifFont(StyleGenericFontFamily::SansSerif, 0),
        mDefaultMonospaceFont(StyleGenericFontFamily::Monospace, 0),
        mDefaultCursiveFont(StyleGenericFontFamily::Cursive, 0),
        mDefaultFantasyFont(StyleGenericFontFamily::Fantasy, 0) {
    // We create mDefaultVariableFont.fontlist with defaultType as the
    // fallback font, and not as part of the font list proper. This way,
    // it can be overwritten should there be a language change.

  void Reset() {
    // Throw away any other LangGroupFontPrefs objects:
    mNext = nullptr;

    // Make GetFontPreferences reinitialize mLangGroupFontPrefs:
    mLangGroup = nullptr;

  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
    size_t n = 0;
    LangGroupFontPrefs* curr = mNext.get();
    while (curr) {
      n += aMallocSizeOf(curr);

      // Measurement of the following members may be added later if DMD finds
      // it is worthwhile:
      // - mLangGroup
      // - mDefault*Font

      curr = curr->mNext.get();
    return n;

  // Initialize this with the data for a given language
  void Initialize(nsStaticAtom* aLangGroupAtom);

   * Get the default font for the given language and generic font ID.
   * aLanguage may not be nullptr.
   * This object is read-only, you must copy the font to modify it.
   * When aFontID is kPresContext_DefaultVariableFontID or
   * kPresContext_DefaultFixedFontID (which equals MozFixed, which is used for
   * the -moz-fixed generic),
   * the nsFont returned has its name as a CSS generic family (serif or
   * sans-serif for the former, monospace for the latter), and its size
   * as the default font size for variable or fixed fonts for the
   * language group.
   * For aFontID corresponding to a CSS Generic, the nsFont returned has
   * its name set to that generic font's name, and its size set to
   * the user's preference for font size for that generic and the
   * given language.
  const nsFont* GetDefaultFont(StyleGenericFontFamily aFamily) const {
    switch (aFamily) {
      // Special (our default variable width font and fixed width font)
      case StyleGenericFontFamily::None:
        return &mDefaultVariableFont;
      case StyleGenericFontFamily::MozFixed:
        return &mDefaultFixedFont;
      // CSS
      case StyleGenericFontFamily::Serif:
        return &mDefaultSerifFont;
      case StyleGenericFontFamily::SansSerif:
        return &mDefaultSansSerifFont;
      case StyleGenericFontFamily::Monospace:
        return &mDefaultMonospaceFont;
      case StyleGenericFontFamily::Cursive:
        return &mDefaultCursiveFont;
      case StyleGenericFontFamily::Fantasy:
        return &mDefaultFantasyFont;
        MOZ_ASSERT_UNREACHABLE("invalid font id");
        return nullptr;

  nsStaticAtom* mLangGroup;
  nscoord mMinimumFontSize;
  nsFont mDefaultVariableFont;
  nsFont mDefaultFixedFont;
  nsFont mDefaultSerifFont;
  nsFont mDefaultSansSerifFont;
  nsFont mDefaultMonospaceFont;
  nsFont mDefaultCursiveFont;
  nsFont mDefaultFantasyFont;
  mozilla::UniquePtr<LangGroupFontPrefs> mNext;

 * Some functionality that has historically lived on nsPresContext does not
 * actually need to be per-document. This singleton class serves as a host
 * for that functionality. We delegate to it from nsPresContext where
 * appropriate, and use it standalone in some cases as well.
class StaticPresData {
  // Initialization and shutdown of the singleton. Called exactly once.
  static void Init();
  static void Shutdown();

  // Gets an instance of the singleton. Infallible between the calls to Init
  // and Shutdown.
  static StaticPresData* Get();

   * Given a language, get the language group name, which can
   * be used as an argument to LangGroupFontPrefs::Initialize()
   * aNeedsToCache is used for two things.  If null, it indicates that
   * the nsLanguageAtomService is safe to cache the result of the
   * language group lookup, either because we're on the main thread,
   * or because we're on a style worker thread but the font lock has
   * been acquired.  If non-null, it indicates that it's not safe to
   * cache the result of the language group lookup (because we're on
   * a style worker thread without the lock acquired).  In this case,
   * GetLanguageGroup will store true in *aNeedsToCache true if we
   * would have cached the result of a new lookup, and false if we
   * were able to use an existing cached result.  Thus, callers that
   * get a true *aNeedsToCache outparam value should make an effort
   * to re-call GetLanguageGroup when it is safe to cache, to avoid
   * recomputing the language group again later.
  nsStaticAtom* GetLangGroup(nsAtom* aLanguage,
                             bool* aNeedsToCache = nullptr) const;

   * Same as GetLangGroup, but will not cache the result
  nsStaticAtom* GetUncachedLangGroup(nsAtom* aLanguage) const;

   * Fetch the user's font preferences for the given aLanguage's
   * langugage group.
   * The original code here is pretty old, and includes an optimization
   * whereby language-specific prefs are read per-document, and the
   * results are stored in a linked list, which is assumed to be very short
   * since most documents only ever use one language.
   * Storing this per-session rather than per-document would almost certainly
   * be fine. But just to be on the safe side, we leave the old mechanism as-is,
   * with an additional per-session cache that new callers can use if they don't
   * have a PresContext.
   * See comment on GetLangGroup for the usage of aNeedsToCache.
  const LangGroupFontPrefs* GetFontPrefsForLang(nsAtom* aLanguage,
                                                bool* aNeedsToCache = nullptr);
  const nsFont* GetDefaultFont(uint8_t aFontID, nsAtom* aLanguage,
                               const LangGroupFontPrefs* aPrefs) const;

  void InvalidateFontPrefs() { mLangGroupFontPrefs.Reset(); }

  ~StaticPresData() = default;

  nsLanguageAtomService* mLangService;
  LangGroupFontPrefs mLangGroupFontPrefs;

}  // namespace mozilla

#endif  // mozilla_StaticPresData_h