Backed out 3 changesets (bug 1537594, bug 1537575) for causing build bustages on mathml/nsMathMLChar.cpp CLOSED TREE
authorarthur.iakab <aiakab@mozilla.com>
Mon, 01 Apr 2019 23:41:04 +0300
changeset 467442 8d2f695cecaf1cbbaa38623569e55357ab8cd5a9
parent 467441 63888044e37b35be11f43be8b10b0a17055e9a6d
child 467443 8cfba39a9c9befbd77bb25dbcbfcf5d64693751a
push id35799
push usercbrindusan@mozilla.com
push dateTue, 02 Apr 2019 08:35:12 +0000
treeherdermozilla-central@ea0977445697 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1537594, 1537575
milestone68.0a1
backs out7375a830b5ef05e6d3049aed28b979f591a3dd12
0cd1411e2fb32f57c3ed90914f5770932eff139f
c7565f50239a1fba96daf6a95a9a710d1b9967d2
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1537594, bug 1537575) for causing build bustages on mathml/nsMathMLChar.cpp CLOSED TREE Backed out changeset 7375a830b5ef (bug 1537594) Backed out changeset 0cd1411e2fb3 (bug 1537575) Backed out changeset c7565f50239a (bug 1537575)
browser/components/preferences/fonts.js
dom/canvas/CanvasRenderingContext2D.cpp
gfx/src/nsFont.cpp
gfx/src/nsFont.h
gfx/thebes/gfxFcPlatformFontList.cpp
gfx/thebes/gfxFcPlatformFontList.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFontEntry.h
gfx/thebes/gfxFontFamilyList.h
gfx/thebes/gfxPlatformFontList.cpp
gfx/thebes/gfxPlatformFontList.h
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
gfx/thebes/gfxTypes.h
layout/base/PresShell.cpp
layout/base/StaticPresData.cpp
layout/base/StaticPresData.h
layout/base/nsLayoutUtils.cpp
layout/generic/nsSimplePageSequenceFrame.cpp
layout/generic/nsTextFrame.cpp
layout/inspector/InspectorFontFace.cpp
layout/mathml/nsMathMLChar.cpp
layout/style/GeckoBindings.cpp
layout/style/GeckoBindings.h
layout/style/ServoBindings.toml
layout/style/ServoTypes.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
modules/libpref/init/all.js
servo/components/style/font_metrics.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/properties/cascade.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhands/font.mako.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/specified/font.rs
servo/ports/geckolib/cbindgen.toml
--- a/browser/components/preferences/fonts.js
+++ b/browser/components/preferences/fonts.js
@@ -10,17 +10,17 @@
 const kDefaultFontType          = "font.default.%LANG%";
 const kFontNameFmtSerif         = "font.name.serif.%LANG%";
 const kFontNameFmtSansSerif     = "font.name.sans-serif.%LANG%";
 const kFontNameFmtMonospace     = "font.name.monospace.%LANG%";
 const kFontNameListFmtSerif     = "font.name-list.serif.%LANG%";
 const kFontNameListFmtSansSerif = "font.name-list.sans-serif.%LANG%";
 const kFontNameListFmtMonospace = "font.name-list.monospace.%LANG%";
 const kFontSizeFmtVariable      = "font.size.variable.%LANG%";
-const kFontSizeFmtFixed         = "font.size.monospace.%LANG%";
+const kFontSizeFmtFixed         = "font.size.fixed.%LANG%";
 const kFontMinSizeFmt           = "font.minimum-size.%LANG%";
 
 document.documentElement.addEventListener("dialoghelp", window.top.openPrefsHelp);
 
 Preferences.addAll([
   { id: "font.language.group", type: "wstring" },
   { id: "browser.display.use_document_fonts", type: "int" },
   { id: "intl.charset.fallback.override", type: "string" },
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3906,18 +3906,18 @@ gfxFontGroup* CanvasRenderingContext2D::
       gfxTextPerfMetrics* tp = nullptr;
       if (presShell && !presShell->IsDestroying()) {
         tp = presShell->GetPresContext()->GetTextPerfMetrics();
       }
       int32_t perDevPixel, perCSSPixel;
       GetAppUnitsValues(&perDevPixel, &perCSSPixel);
       gfxFloat devToCssSize = gfxFloat(perDevPixel) / gfxFloat(perCSSPixel);
       CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(
-          FontFamilyList(StyleGenericFontFamily::SansSerif), &style, tp,
-          nullptr, devToCssSize);
+          FontFamilyList(eFamily_sans_serif), &style, tp, nullptr,
+          devToCssSize);
       if (CurrentState().fontGroup) {
         CurrentState().font = kDefaultFontStyle;
       } else {
         NS_ERROR("Default canvas font is invalid");
       }
     }
   }
 
--- a/gfx/src/nsFont.cpp
+++ b/gfx/src/nsFont.cpp
@@ -16,17 +16,17 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/gfx/2D.h"
 
 using namespace mozilla;
 
 nsFont::nsFont(const FontFamilyList& aFontlist, nscoord aSize)
     : fontlist(aFontlist), size(aSize) {}
 
-nsFont::nsFont(StyleGenericFontFamily aGenericType, nscoord aSize)
+nsFont::nsFont(FontFamilyType aGenericType, nscoord aSize)
     : fontlist(aGenericType), size(aSize) {}
 
 nsFont::nsFont(const nsFont& aOther) = default;
 
 nsFont::nsFont() {}
 
 nsFont::~nsFont() {}
 
--- a/gfx/src/nsFont.h
+++ b/gfx/src/nsFont.h
@@ -16,16 +16,32 @@
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/RefPtr.h"  // for RefPtr
 #include "nsColor.h"         // for nsColor and NS_RGBA
 #include "nsCoord.h"         // for nscoord
 #include "nsTArray.h"        // for nsTArray
 
 struct gfxFontStyle;
 
+// IDs for generic fonts
+// NOTE: 0, 1 are reserved for the special IDs of the default variable
+// and fixed fonts in the presentation context, see nsPresContext.h
+const uint8_t kGenericFont_NONE = 0x00;
+// Special
+const uint8_t kGenericFont_moz_variable =
+    0x00;  // for the default variable width font
+const uint8_t kGenericFont_moz_fixed =
+    0x01;  // our special "use the user's fixed font"
+// CSS
+const uint8_t kGenericFont_serif = 0x02;
+const uint8_t kGenericFont_sans_serif = 0x04;
+const uint8_t kGenericFont_monospace = 0x08;
+const uint8_t kGenericFont_cursive = 0x10;
+const uint8_t kGenericFont_fantasy = 0x20;
+
 // Font structure.
 struct nsFont {
   typedef mozilla::FontStretch FontStretch;
   typedef mozilla::FontSlantStyle FontSlantStyle;
   typedef mozilla::FontWeight FontWeight;
 
   // List of font families, either named or generic.
   // This contains a RefPtr and a uint32_t field.
@@ -96,17 +112,17 @@ struct nsFont {
   // Force this font to not be considered a 'generic' font, even if
   // the name is the same as a CSS generic font family.
   bool systemFont = false;
 
   // initialize the font with a fontlist
   nsFont(const mozilla::FontFamilyList& aFontlist, nscoord aSize);
 
   // initialize the font with a single generic
-  nsFont(mozilla::StyleGenericFontFamily, nscoord aSize);
+  nsFont(mozilla::FontFamilyType aGenericType, nscoord aSize);
 
   // Make a copy of the given font
   nsFont(const nsFont& aFont);
 
   // leave members uninitialized
   nsFont();
 
   ~nsFont();
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -1967,20 +1967,25 @@ bool gfxFcPlatformFontList::GetStandardF
     }
   }
 
   // didn't find localized name, leave family name blank
   return true;
 }
 
 void gfxFcPlatformFontList::AddGenericFonts(
-    mozilla::StyleGenericFontFamily aGenericType, nsAtom* aLanguage,
+    mozilla::FontFamilyType aGenericType, nsAtom* aLanguage,
     nsTArray<FamilyAndGeneric>& aFamilyList) {
   bool usePrefFontList = false;
 
+  // treat -moz-fixed as monospace
+  if (aGenericType == eFamily_moz_fixed) {
+    aGenericType = eFamily_monospace;
+  }
+
   const char* generic = GetGenericName(aGenericType);
   NS_ASSERTION(generic, "weird generic font type");
   if (!generic) {
     return;
   }
 
   // By default, most font prefs on Linux map to "use fontconfig"
   // keywords. So only need to explicitly lookup font pref if
--- a/gfx/thebes/gfxFcPlatformFontList.h
+++ b/gfx/thebes/gfxFcPlatformFontList.h
@@ -296,17 +296,17 @@ class gfxFcPlatformFontList : public gfx
                           gfxFloat aDevToCssSize = 1.0) override;
 
   bool GetStandardFamilyName(const nsCString& aFontName,
                              nsACString& aFamilyName) override;
 
   FcConfig* GetLastConfig() const { return mLastConfig; }
 
   // override to use fontconfig lookup for generics
-  void AddGenericFonts(mozilla::StyleGenericFontFamily, nsAtom* aLanguage,
+  void AddGenericFonts(mozilla::FontFamilyType aGenericType, nsAtom* aLanguage,
                        nsTArray<FamilyAndGeneric>& aFamilyList) override;
 
   void ClearLangGroupPrefFonts() override;
 
   // clear out cached generic-lang ==> family-list mappings
   void ClearGenericMappings() { mGenericMappings.Clear(); }
 
   // map lang group ==> lang string
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gfxFont.h"
 
 #include "mozilla/BinarySearch.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/gfx/2D.h"
-#include "mozilla/IntegerRange.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/SVGContextPaint.h"
 
 #include "mozilla/Logging.h"
 
 #include "nsITimer.h"
 
@@ -3996,29 +3995,28 @@ bool gfxFont::TryGetMathTable() {
 
   return !!mMathTable;
 }
 
 /* static */
 void SharedFontList::Initialize() {
   sEmpty = new SharedFontList();
 
-  for (auto i : IntegerRange(ArrayLength(sSingleGenerics))) {
-    auto type = static_cast<StyleGenericFontFamily>(i);
-    if (type != StyleGenericFontFamily::None) {
-      sSingleGenerics[i] = new SharedFontList(type);
-    }
+  for (uint8_t i = 0; i < uint8_t(eFamily_generic_count_including_special);
+       ++i) {
+    auto type = static_cast<FontFamilyType>(i + uint8_t(eFamily_generic_first));
+    sSingleGenerics[i] = new SharedFontList(type);
   }
 }
 
 /* static */
 void SharedFontList::Shutdown() {
   sEmpty = nullptr;
 
   for (auto& sharedFontList : sSingleGenerics) {
     sharedFontList = nullptr;
   }
 }
 
 StaticRefPtr<SharedFontList> SharedFontList::sEmpty;
 
 StaticRefPtr<SharedFontList>
-    SharedFontList::sSingleGenerics[size_t(StyleGenericFontFamily::MozEmoji)];
+    SharedFontList::sSingleGenerics[eFamily_generic_count_including_special];
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -932,33 +932,33 @@ struct FontFamily {
   bool mIsShared;
 };
 
 // Struct used in the gfxFontGroup font list to keep track of a font family
 // together with the CSS generic (if any) that was mapped to it in this
 // particular case (so it can be reported to the DevTools font inspector).
 struct FamilyAndGeneric final {
   FamilyAndGeneric()
-      : mFamily(), mGeneric(mozilla::StyleGenericFontFamily::None) {}
+      : mFamily(), mGeneric(mozilla::FontFamilyType::eFamily_none) {}
   FamilyAndGeneric(const FamilyAndGeneric& aOther)
       : mFamily(aOther.mFamily), mGeneric(aOther.mGeneric) {}
-  explicit FamilyAndGeneric(gfxFontFamily* aFamily,
-                            mozilla::StyleGenericFontFamily aGeneric =
-                                mozilla::StyleGenericFontFamily::None)
+  explicit FamilyAndGeneric(
+      gfxFontFamily* aFamily,
+      mozilla::FontFamilyType aGeneric = mozilla::FontFamilyType::eFamily_none)
       : mFamily(aFamily), mGeneric(aGeneric) {}
-  explicit FamilyAndGeneric(mozilla::fontlist::Family* aFamily,
-                            mozilla::StyleGenericFontFamily aGeneric =
-                                mozilla::StyleGenericFontFamily::None)
+  explicit FamilyAndGeneric(
+      mozilla::fontlist::Family* aFamily,
+      mozilla::FontFamilyType aGeneric = mozilla::FontFamilyType::eFamily_none)
       : mFamily(aFamily), mGeneric(aGeneric) {}
-  explicit FamilyAndGeneric(const FontFamily& aFamily,
-                            mozilla::StyleGenericFontFamily aGeneric =
-                                mozilla::StyleGenericFontFamily::None)
+  explicit FamilyAndGeneric(
+      const FontFamily& aFamily,
+      mozilla::FontFamilyType aGeneric = mozilla::FontFamilyType::eFamily_none)
       : mFamily(aFamily), mGeneric(aGeneric) {}
 
   bool operator==(const FamilyAndGeneric& aOther) const {
-    return mFamily == aOther.mFamily && mGeneric == aOther.mGeneric;
+    return (mFamily == aOther.mFamily && mGeneric == aOther.mGeneric);
   }
 
   FontFamily mFamily;
-  mozilla::StyleGenericFontFamily mGeneric;
+  mozilla::FontFamilyType mGeneric;
 };
 
 #endif
--- a/gfx/thebes/gfxFontFamilyList.h
+++ b/gfx/thebes/gfxFontFamilyList.h
@@ -5,158 +5,213 @@
 
 #ifndef GFX_FONT_FAMILY_LIST_H
 #define GFX_FONT_FAMILY_LIST_H
 
 #include "nsAtom.h"
 #include "nsDebug.h"
 #include "nsISupportsImpl.h"
 #include "nsString.h"
-#include "nsStyleConsts.h"
 #include "nsUnicharUtils.h"
 #include "nsTArray.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TimeStamp.h"
 
 namespace mozilla {
 
 /**
+ * type of font family name, either a name (e.g. Helvetica) or a
+ * generic (e.g. serif, sans-serif), with the ability to distinguish
+ * between unquoted and quoted names for serializaiton
+ */
+
+enum FontFamilyType : uint8_t {
+  eFamily_none = 0,  // used when finding generics
+
+  // explicitly named font family (e.g. Helvetica)
+  eFamily_named,
+  eFamily_named_quoted,
+
+  // generics
+  eFamily_serif,  // pref font code relies on this ordering!!!
+  eFamily_sans_serif,
+  eFamily_monospace,
+  eFamily_cursive,
+  eFamily_fantasy,
+
+  // special
+  eFamily_moz_variable,
+  eFamily_moz_fixed,
+  eFamily_moz_emoji,
+
+  eFamily_generic_first = eFamily_serif,
+  eFamily_generic_last = eFamily_fantasy,
+  eFamily_generic_last_including_special = eFamily_moz_emoji,
+
+  eFamily_generic_count = eFamily_generic_last - eFamily_generic_first + 1,
+  eFamily_generic_count_including_special =
+      eFamily_generic_last_including_special - eFamily_generic_first + 1,
+};
+
+enum QuotedName { eQuotedName, eUnquotedName };
+
+/**
  * font family name, an Atom for the name if not a generic and
  * a font type indicated named family or which generic family
  */
 
 struct FontFamilyName final {
-  using Syntax = StyleFontFamilyNameSyntax;
-
-  FontFamilyName() = delete;
+  FontFamilyName() : mType(eFamily_none) {}
 
   // named font family - e.g. Helvetica
-  explicit FontFamilyName(nsAtom* aFamilyName, Syntax aSyntax)
-      : mName(aFamilyName), mSyntax(aSyntax) {}
+  explicit FontFamilyName(nsAtom* aFamilyName,
+                          QuotedName aQuoted = eUnquotedName) {
+    mType = (aQuoted == eQuotedName) ? eFamily_named_quoted : eFamily_named;
+    mName = aFamilyName;
+  }
 
-  explicit FontFamilyName(const nsACString& aFamilyName, Syntax aSyntax)
-      : mName(NS_Atomize(aFamilyName)), mSyntax(aSyntax) {}
+  explicit FontFamilyName(const nsACString& aFamilyName,
+                          QuotedName aQuoted = eUnquotedName) {
+    mType = (aQuoted == eQuotedName) ? eFamily_named_quoted : eFamily_named;
+    mName = NS_Atomize(aFamilyName);
+  }
 
   // generic font family - e.g. sans-serif
-  explicit FontFamilyName(StyleGenericFontFamily aGeneric)
-      : mGeneric(aGeneric) {
-    MOZ_ASSERT(mGeneric != StyleGenericFontFamily::None);
+  explicit FontFamilyName(FontFamilyType aType) {
+    NS_ASSERTION(aType != eFamily_named && aType != eFamily_named_quoted &&
+                     aType != eFamily_none,
+                 "expected a generic font type");
+    mName = nullptr;
+    mType = aType;
   }
 
-  FontFamilyName(const FontFamilyName&) = default;
+  FontFamilyName(const FontFamilyName& aCopy) {
+    mType = aCopy.mType;
+    mName = aCopy.mName;
+  }
 
-  bool IsNamed() const { return !!mName; }
+  bool IsNamed() const {
+    return mType == eFamily_named || mType == eFamily_named_quoted;
+  }
 
   bool IsGeneric() const { return !IsNamed(); }
 
   void AppendToString(nsACString& aFamilyList, bool aQuotes = true) const {
-    if (IsNamed()) {
-      if (mSyntax == Syntax::Identifiers) {
-        return aFamilyList.Append(nsAtomCString(mName));
-      }
-      if (aQuotes) {
-        aFamilyList.Append('"');
-      }
-      aFamilyList.Append(nsAtomCString(mName));
-      if (aQuotes) {
-        aFamilyList.Append('"');
-      }
-      return;
-    }
-    switch (mGeneric) {
-      case StyleGenericFontFamily::None:
-      case StyleGenericFontFamily::MozEmoji:
-        MOZ_FALLTHROUGH_ASSERT("Should never appear in a font-family name!");
-      case StyleGenericFontFamily::Serif:
+    switch (mType) {
+      case eFamily_named:
+        aFamilyList.Append(nsAtomCString(mName));
+        break;
+      case eFamily_named_quoted:
+        if (aQuotes) {
+          aFamilyList.Append('"');
+        }
+        aFamilyList.Append(nsAtomCString(mName));
+        if (aQuotes) {
+          aFamilyList.Append('"');
+        }
+        break;
+      case eFamily_serif:
         aFamilyList.AppendLiteral("serif");
         break;
-      case StyleGenericFontFamily::SansSerif:
+      case eFamily_sans_serif:
         aFamilyList.AppendLiteral("sans-serif");
         break;
-      case StyleGenericFontFamily::Monospace:
+      case eFamily_monospace:
         aFamilyList.AppendLiteral("monospace");
         break;
-      case StyleGenericFontFamily::Cursive:
+      case eFamily_cursive:
         aFamilyList.AppendLiteral("cursive");
         break;
-      case StyleGenericFontFamily::Fantasy:
+      case eFamily_fantasy:
         aFamilyList.AppendLiteral("fantasy");
         break;
+      case eFamily_moz_fixed:
+        aFamilyList.AppendLiteral("-moz-fixed");
+        break;
       default:
-        MOZ_ASSERT_UNREACHABLE("Unknown generic font-family!");
         break;
     }
   }
 
   // helper method that converts generic names to the right enum value
   static FontFamilyName Convert(const nsACString& aFamilyOrGenericName) {
     // should only be passed a single font - not entirely correct, a family
     // *could* have a comma in it but in practice never does so
     // for debug purposes this is fine
     NS_ASSERTION(aFamilyOrGenericName.FindChar(',') == -1,
                  "Convert method should only be passed a single family name");
 
-    auto genericType = StyleGenericFontFamily::None;
+    FontFamilyType genericType = eFamily_none;
     if (aFamilyOrGenericName.LowerCaseEqualsLiteral("serif")) {
-      genericType = StyleGenericFontFamily::Serif;
+      genericType = eFamily_serif;
     } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("sans-serif")) {
-      genericType = StyleGenericFontFamily::SansSerif;
-    } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("monospace") ||
-               aFamilyOrGenericName.LowerCaseEqualsLiteral("-moz-fixed")) {
-      genericType = StyleGenericFontFamily::Monospace;
+      genericType = eFamily_sans_serif;
+    } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("monospace")) {
+      genericType = eFamily_monospace;
     } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("cursive")) {
-      genericType = StyleGenericFontFamily::Cursive;
+      genericType = eFamily_cursive;
     } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("fantasy")) {
-      genericType = StyleGenericFontFamily::Fantasy;
+      genericType = eFamily_fantasy;
+    } else if (aFamilyOrGenericName.LowerCaseEqualsLiteral("-moz-fixed")) {
+      genericType = eFamily_moz_fixed;
     } else {
-      return FontFamilyName(aFamilyOrGenericName, Syntax::Identifiers);
+      return FontFamilyName(aFamilyOrGenericName, eUnquotedName);
     }
 
     return FontFamilyName(genericType);
   }
 
-  RefPtr<nsAtom> mName;  // null if mGeneric != Default
-  StyleFontFamilyNameSyntax mSyntax = StyleFontFamilyNameSyntax::Quoted;
-  StyleGenericFontFamily mGeneric = StyleGenericFontFamily::None;
+  FontFamilyType mType;
+  RefPtr<nsAtom> mName;  // null if mType != eFamily_named
 };
 
 inline bool operator==(const FontFamilyName& a, const FontFamilyName& b) {
-  return a.mName == b.mName && a.mSyntax == b.mSyntax &&
-         a.mGeneric == b.mGeneric;
+  return a.mType == b.mType && a.mName == b.mName;
 }
 
 /**
  * A refcounted array of FontFamilyNames.  We use this to store the specified
  * and computed value of the font-family property.
  *
  * TODO(heycam): It might better to define this type (and FontFamilyList and
  * FontFamilyName) in Rust.
  */
 class SharedFontList {
-  using Syntax = StyleFontFamilyNameSyntax;
-
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedFontList);
 
-  SharedFontList() = default;
+  SharedFontList() {}
 
-  explicit SharedFontList(StyleGenericFontFamily aGenericType)
+  explicit SharedFontList(FontFamilyType aGenericType)
       : mNames{FontFamilyName(aGenericType)} {}
 
-  SharedFontList(nsAtom* aFamilyName, Syntax aSyntax)
-      : mNames{FontFamilyName(aFamilyName, aSyntax)} {}
+  SharedFontList(nsAtom* aFamilyName, QuotedName aQuoted)
+      : mNames{FontFamilyName(aFamilyName, aQuoted)} {}
 
-  SharedFontList(const nsACString& aFamilyName, Syntax aSyntax)
-      : mNames{FontFamilyName(aFamilyName, aSyntax)} {}
+  SharedFontList(const nsACString& aFamilyName, QuotedName aQuoted)
+      : mNames{FontFamilyName(aFamilyName, aQuoted)} {}
+
+  explicit SharedFontList(const FontFamilyName& aName) : mNames{aName} {}
 
   explicit SharedFontList(nsTArray<FontFamilyName>&& aNames)
       : mNames(std::move(aNames)) {}
 
+  FontFamilyType FirstGeneric() const {
+    for (const FontFamilyName& name : mNames) {
+      if (name.IsGeneric()) {
+        return name.mType;
+      }
+    }
+    return eFamily_none;
+  }
+
+  bool HasGeneric() const { return FirstGeneric() != eFamily_none; }
+
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
     size_t n = 0;
     n += aMallocSizeOf(this);
     n += mNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
     return n;
   }
 
   size_t SizeOfIncludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const {
@@ -168,51 +223,59 @@ class SharedFontList {
   }
 
   const nsTArray<FontFamilyName> mNames;
 
   static void Initialize();
   static void Shutdown();
   static StaticRefPtr<SharedFontList> sEmpty;
   static StaticRefPtr<SharedFontList>
-      sSingleGenerics[size_t(StyleGenericFontFamily::MozEmoji)];
+      sSingleGenerics[eFamily_generic_count_including_special];
 
  private:
   ~SharedFontList() = default;
 };
 
 /**
  * font family list, array of font families and a default font type.
  * font family names are either named strings or generics. the default
  * font type is used to preserve the variable font fallback behavior
  */
 class FontFamilyList {
-  using Syntax = StyleFontFamilyNameSyntax;
+ public:
+  FontFamilyList()
+      : mFontlist(WrapNotNull(SharedFontList::sEmpty.get())),
+        mDefaultFontType(eFamily_none) {}
 
- public:
-  FontFamilyList() : mFontlist(WrapNotNull(SharedFontList::sEmpty.get())) {}
+  explicit FontFamilyList(FontFamilyType aGenericType)
+      : mFontlist(MakeNotNull<SharedFontList*>(aGenericType)),
+        mDefaultFontType(eFamily_none) {}
 
-  explicit FontFamilyList(StyleGenericFontFamily aGenericType)
-      : mFontlist(MakeNotNull<SharedFontList*>(aGenericType)) {}
+  FontFamilyList(nsAtom* aFamilyName, QuotedName aQuoted)
+      : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aQuoted)),
+        mDefaultFontType(eFamily_none) {}
 
-  FontFamilyList(nsAtom* aFamilyName, Syntax aSyntax)
-      : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aSyntax)) {}
+  FontFamilyList(const nsACString& aFamilyName, QuotedName aQuoted)
+      : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aQuoted)),
+        mDefaultFontType(eFamily_none) {}
 
-  FontFamilyList(const nsACString& aFamilyName, Syntax aSyntax)
-      : mFontlist(MakeNotNull<SharedFontList*>(aFamilyName, aSyntax)) {}
+  explicit FontFamilyList(const FontFamilyName& aName)
+      : mFontlist(MakeNotNull<SharedFontList*>(aName)),
+        mDefaultFontType(eFamily_none) {}
 
   explicit FontFamilyList(nsTArray<FontFamilyName>&& aNames)
-      : mFontlist(MakeNotNull<SharedFontList*>(std::move(aNames))) {}
+      : mFontlist(MakeNotNull<SharedFontList*>(std::move(aNames))),
+        mDefaultFontType(eFamily_none) {}
 
   FontFamilyList(const FontFamilyList& aOther)
       : mFontlist(aOther.mFontlist),
         mDefaultFontType(aOther.mDefaultFontType) {}
 
   explicit FontFamilyList(NotNull<SharedFontList*> aFontList)
-      : mFontlist(aFontList) {}
+      : mFontlist(aFontList), mDefaultFontType(eFamily_none) {}
 
   void SetFontlist(nsTArray<FontFamilyName>&& aNames) {
     mFontlist = MakeNotNull<SharedFontList*>(std::move(aNames));
   }
 
   void SetFontlist(NotNull<SharedFontList*> aFontlist) {
     mFontlist = aFontlist;
   }
@@ -224,77 +287,77 @@ class FontFamilyList {
   NotNull<SharedFontList*> GetFontlist() const { return mFontlist; }
 
   bool Equals(const FontFamilyList& aFontlist) const {
     return (mFontlist == aFontlist.mFontlist ||
             mFontlist->mNames == aFontlist.mFontlist->mNames) &&
            mDefaultFontType == aFontlist.mDefaultFontType;
   }
 
+  FontFamilyType FirstGeneric() const { return mFontlist->FirstGeneric(); }
+
+  bool HasGeneric() const { return mFontlist->HasGeneric(); }
+
   bool HasDefaultGeneric() const {
-    if (mDefaultFontType == StyleGenericFontFamily::None) {
-      return false;
-    }
     for (const FontFamilyName& name : mFontlist->mNames) {
-      if (name.mGeneric == mDefaultFontType) {
+      if (name.mType == mDefaultFontType) {
         return true;
       }
     }
     return false;
   }
 
   // Find the first generic (but ignoring cursive and fantasy, as they are
   // rarely configured in any useful way) in the list.
   // If found, move it to the start and return true; else return false.
   bool PrioritizeFirstGeneric() {
     uint32_t len = mFontlist->mNames.Length();
     for (uint32_t i = 0; i < len; i++) {
       const FontFamilyName name = mFontlist->mNames[i];
       if (name.IsGeneric()) {
-        if (name.mGeneric == StyleGenericFontFamily::Cursive ||
-            name.mGeneric == StyleGenericFontFamily::Fantasy) {
+        if (name.mType == eFamily_cursive || name.mType == eFamily_fantasy) {
           continue;
         }
         if (i > 0) {
           nsTArray<FontFamilyName> names;
           names.AppendElements(mFontlist->mNames);
           names.RemoveElementAt(i);
           names.InsertElementAt(0, name);
           SetFontlist(std::move(names));
         }
         return true;
       }
     }
     return false;
   }
 
-  void PrependGeneric(StyleGenericFontFamily aGeneric) {
+  void PrependGeneric(FontFamilyType aType) {
     nsTArray<FontFamilyName> names;
     names.AppendElements(mFontlist->mNames);
-    names.InsertElementAt(0, FontFamilyName(aGeneric));
+    names.InsertElementAt(0, FontFamilyName(aType));
     SetFontlist(std::move(names));
   }
 
   void ToString(nsACString& aFamilyList, bool aQuotes = true,
                 bool aIncludeDefault = false) const {
     const nsTArray<FontFamilyName>& names = mFontlist->mNames;
     aFamilyList.Truncate();
     uint32_t len = names.Length();
     for (uint32_t i = 0; i < len; i++) {
       if (i != 0) {
         aFamilyList.Append(',');
       }
       const FontFamilyName& name = names[i];
       name.AppendToString(aFamilyList, aQuotes);
     }
-    if (aIncludeDefault && mDefaultFontType != StyleGenericFontFamily::None) {
+    if (aIncludeDefault && mDefaultFontType != eFamily_none) {
       if (!aFamilyList.IsEmpty()) {
         aFamilyList.Append(',');
       }
-      if (mDefaultFontType == StyleGenericFontFamily::Serif) {
+      if (mDefaultFontType == eFamily_serif) {
         aFamilyList.AppendLiteral("serif");
       } else {
         aFamilyList.AppendLiteral("sans-serif");
       }
     }
   }
 
   // searches for a specific non-generic name, case-insensitive comparison
@@ -307,21 +370,20 @@ class FontFamilyList {
       nsDependentAtomString listname(name.mName);
       if (listname.Equals(fam, nsCaseInsensitiveStringComparator())) {
         return true;
       }
     }
     return false;
   }
 
-  StyleGenericFontFamily GetDefaultFontType() const { return mDefaultFontType; }
-  void SetDefaultFontType(StyleGenericFontFamily aType) {
-    NS_ASSERTION(aType == StyleGenericFontFamily::None ||
-                     aType == StyleGenericFontFamily::Serif ||
-                     aType == StyleGenericFontFamily::SansSerif,
+  FontFamilyType GetDefaultFontType() const { return mDefaultFontType; }
+  void SetDefaultFontType(FontFamilyType aType) {
+    NS_ASSERTION(aType == eFamily_none || aType == eFamily_serif ||
+                     aType == eFamily_sans_serif,
                  "default font type must be either serif or sans-serif");
     mDefaultFontType = aType;
   }
 
   // memory reporting
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
     size_t n = 0;
     n += mFontlist->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
@@ -329,18 +391,17 @@ class FontFamilyList {
   }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
  protected:
   NotNull<RefPtr<SharedFontList>> mFontlist;
-  StyleGenericFontFamily mDefaultFontType =
-      StyleGenericFontFamily::None;  // or serif, or sans-serif
+  FontFamilyType mDefaultFontType;  // none, serif or sans-serif
 };
 
 inline bool operator==(const FontFamilyList& a, const FontFamilyList& b) {
   return a.Equals(b);
 }
 
 inline bool operator!=(const FontFamilyList& a, const FontFamilyList& b) {
   return !a.Equals(b);
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -886,17 +886,17 @@ void gfxPlatformFontList::RemoveCmap(con
   CharMapHashKey* found =
       mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap));
   if (found && found->GetKey() == aCharMap) {
     mSharedCmaps.RemoveEntry(found);
   }
 }
 
 void gfxPlatformFontList::ResolveGenericFontNames(
-    StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang,
+    FontFamilyType aGenericType, eFontPrefLang aPrefLang,
     PrefFontList* aGenericFamilies) {
   const char* langGroupStr = GetPrefLangName(aPrefLang);
   const char* generic = GetGenericName(aGenericType);
 
   if (!generic) {
     return;
   }
 
@@ -952,40 +952,44 @@ void gfxPlatformFontList::GetFontFamilie
       if (!aGenericFamilies->Contains(f.mFamily)) {
         aGenericFamilies->AppendElement(f.mFamily);
       }
     }
   }
 }
 
 gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup(
-    StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang) {
-  if (aGenericType == StyleGenericFontFamily::MozEmoji) {
+    mozilla::FontFamilyType aGenericType, eFontPrefLang aPrefLang) {
+  // treat -moz-fixed as monospace
+  if (aGenericType == eFamily_moz_fixed) {
+    aGenericType = eFamily_monospace;
+  }
+
+  if (aGenericType == eFamily_moz_emoji) {
     // Emoji font has no lang
     PrefFontList* prefFonts = mEmojiPrefFont.get();
     if (MOZ_UNLIKELY(!prefFonts)) {
       prefFonts = new PrefFontList;
       ResolveEmojiFontNames(prefFonts);
       mEmojiPrefFont.reset(prefFonts);
     }
     return prefFonts;
   }
 
-  auto index = static_cast<size_t>(aGenericType);
-  PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][index].get();
+  PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][aGenericType].get();
   if (MOZ_UNLIKELY(!prefFonts)) {
     prefFonts = new PrefFontList;
     ResolveGenericFontNames(aGenericType, aPrefLang, prefFonts);
-    mLangGroupPrefFonts[aPrefLang][index].reset(prefFonts);
+    mLangGroupPrefFonts[aPrefLang][aGenericType].reset(prefFonts);
   }
   return prefFonts;
 }
 
 void gfxPlatformFontList::AddGenericFonts(
-    mozilla::StyleGenericFontFamily aGenericType, nsAtom* aLanguage,
+    mozilla::FontFamilyType aGenericType, nsAtom* aLanguage,
     nsTArray<FamilyAndGeneric>& aFamilyList) {
   // map lang ==> langGroup
   nsAtom* langGroup = GetLangGroup(aLanguage);
 
   // langGroup ==> prefLang
   eFontPrefLang prefLang = GetFontPrefLangFor(langGroup);
 
   // lookup pref fonts
@@ -1273,42 +1277,42 @@ void gfxPlatformFontList::AppendPrefLang
   }
 
   if (i == aLen) {
     aPrefLangs[aLen] = aAddLang;
     aLen++;
   }
 }
 
-mozilla::StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric(
+mozilla::FontFamilyType gfxPlatformFontList::GetDefaultGeneric(
     eFontPrefLang aLang) {
   if (aLang == eFontPrefLang_Emoji) {
-    return StyleGenericFontFamily::MozEmoji;
+    return eFamily_moz_emoji;
   }
 
   // initialize lang group pref font defaults (i.e. serif/sans-serif)
   if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) {
     mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames));
     for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); i++) {
       nsAutoCString prefDefaultFontType("font.default.");
       prefDefaultFontType.Append(GetPrefLangName(eFontPrefLang(i)));
       nsAutoCString serifOrSans;
       Preferences::GetCString(prefDefaultFontType.get(), serifOrSans);
       if (serifOrSans.EqualsLiteral("sans-serif")) {
-        mDefaultGenericsLangGroup[i] = StyleGenericFontFamily::SansSerif;
+        mDefaultGenericsLangGroup[i] = eFamily_sans_serif;
       } else {
-        mDefaultGenericsLangGroup[i] = StyleGenericFontFamily::Serif;
+        mDefaultGenericsLangGroup[i] = eFamily_serif;
       }
     }
   }
 
   if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
     return mDefaultGenericsLangGroup[uint32_t(aLang)];
   }
-  return StyleGenericFontFamily::Serif;
+  return eFamily_serif;
 }
 
 FontFamily gfxPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle) {
   FontFamily family = GetDefaultFontForPlatform(aStyle);
   if (!family.mIsShared && family.mUnshared) {
     return family;
   }
   // Something has gone wrong and we were unable to retrieve a default font
@@ -1334,40 +1338,50 @@ nsAtom* gfxPlatformFontList::GetLangGrou
   }
   if (!langGroup) {
     langGroup = nsGkAtoms::Unicode;
   }
   return langGroup;
 }
 
 /* static */ const char* gfxPlatformFontList::GetGenericName(
-    StyleGenericFontFamily aGenericType) {
+    FontFamilyType aGenericType) {
   static const char kGeneric_serif[] = "serif";
   static const char kGeneric_sans_serif[] = "sans-serif";
   static const char kGeneric_monospace[] = "monospace";
   static const char kGeneric_cursive[] = "cursive";
   static const char kGeneric_fantasy[] = "fantasy";
 
   // type should be standard generic type at this point
+  NS_ASSERTION(aGenericType >= eFamily_serif && aGenericType <= eFamily_fantasy,
+               "standard generic font family type required");
+
   // map generic type to string
+  const char* generic = nullptr;
   switch (aGenericType) {
-    case StyleGenericFontFamily::Serif:
-      return kGeneric_serif;
-    case StyleGenericFontFamily::SansSerif:
-      return kGeneric_sans_serif;
-    case StyleGenericFontFamily::Monospace:
-      return kGeneric_monospace;
-    case StyleGenericFontFamily::Cursive:
-      return kGeneric_cursive;
-    case StyleGenericFontFamily::Fantasy:
-      return kGeneric_fantasy;
+    case eFamily_serif:
+      generic = kGeneric_serif;
+      break;
+    case eFamily_sans_serif:
+      generic = kGeneric_sans_serif;
+      break;
+    case eFamily_monospace:
+      generic = kGeneric_monospace;
+      break;
+    case eFamily_cursive:
+      generic = kGeneric_cursive;
+      break;
+    case eFamily_fantasy:
+      generic = kGeneric_fantasy;
+      break;
     default:
-      MOZ_ASSERT_UNREACHABLE("Unknown generic");
-      return nullptr;
+      break;
   }
+
+  return generic;
 }
 
 void gfxPlatformFontList::InitLoader() {
   GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad);
   mStartIndex = 0;
   mNumFamilies = mFontInfo->mFontFamiliesToLoad.Length();
   memset(&(mFontInfo->mLoadStats), 0, sizeof(mFontInfo->mLoadStats));
 }
@@ -1485,18 +1499,19 @@ void gfxPlatformFontList::RebuildLocalFo
     it.Get()->GetKey()->RebuildLocalRules();
   }
 }
 
 void gfxPlatformFontList::ClearLangGroupPrefFonts() {
   for (uint32_t i = eFontPrefLang_First;
        i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
     auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
-    for (auto& pref : prefFontsLangGroup) {
-      pref = nullptr;
+    for (uint32_t j = eFamily_generic_first;
+         j < eFamily_generic_first + eFamily_generic_count; j++) {
+      prefFontsLangGroup[j] = nullptr;
     }
   }
   mCJKPrefLangs.Clear();
   mEmojiPrefFont = nullptr;
 }
 
 // Support for memory reporting
 
@@ -1544,17 +1559,19 @@ void gfxPlatformFontList::AddSizeOfExclu
         mExtraNames->mFullnames, aMallocSizeOf);
     aSizes->mFontListSize += SizeOfFontEntryTableExcludingThis(
         mExtraNames->mPostscriptNames, aMallocSizeOf);
   }
 
   for (uint32_t i = eFontPrefLang_First;
        i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
     auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
-    for (const UniquePtr<PrefFontList>& pf : prefFontsLangGroup) {
+    for (uint32_t j = eFamily_generic_first;
+         j < eFamily_generic_first + eFamily_generic_count; j++) {
+      PrefFontList* pf = prefFontsLangGroup[j].get();
       if (pf) {
         aSizes->mFontListSize += pf->ShallowSizeOfExcludingThis(aMallocSizeOf);
       }
     }
   }
 
   aSizes->mFontListSize +=
       mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -253,22 +253,22 @@ class gfxPlatformFontList : public gfxFo
 
   static const gfxFontEntry::ScriptRange sComplexScriptRanges[];
 
   void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) {
     aNumInits = mFontlistInitCount;
     aLoaderState = (uint32_t)mState;
   }
 
-  virtual void AddGenericFonts(mozilla::StyleGenericFontFamily aGenericType,
+  virtual void AddGenericFonts(mozilla::FontFamilyType aGenericType,
                                nsAtom* aLanguage,
                                nsTArray<FamilyAndGeneric>& aFamilyList);
 
-  PrefFontList* GetPrefFontsLangGroup(
-      mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang);
+  PrefFontList* GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
+                                      eFontPrefLang aPrefLang);
 
   // in some situations, need to make decisions about ambiguous characters, may
   // need to look at multiple pref langs
   void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
                     eFontPrefLang aCharLang, eFontPrefLang aPageLang);
 
   // convert a lang group to enum constant (i.e. "zh-TW" ==>
   // eFontPrefLang_ChineseTW)
@@ -290,28 +290,27 @@ class gfxPlatformFontList : public gfxFo
   // returns true if a pref lang is CJK
   static bool IsLangCJK(eFontPrefLang aLang);
 
   // helper method to add a pref lang to an array, if not already in array
   static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen,
                              eFontPrefLang aAddLang);
 
   // default serif/sans-serif choice based on font.default.xxx prefs
-  mozilla::StyleGenericFontFamily GetDefaultGeneric(eFontPrefLang aLang);
+  mozilla::FontFamilyType GetDefaultGeneric(eFontPrefLang aLang);
 
   // Returns true if the font family whitelist is not empty.
   bool IsFontFamilyWhitelistActive();
 
   static void FontWhitelistPrefChanged(const char* aPref, void* aClosure);
 
   bool AddWithLegacyFamilyName(const nsACString& aLegacyName,
                                gfxFontEntry* aFontEntry);
 
-  static const char* GetGenericName(
-      mozilla::StyleGenericFontFamily aGenericType);
+  static const char* GetGenericName(mozilla::FontFamilyType aGenericType);
 
  protected:
   class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable {
    public:
     InitOtherFamilyNamesRunnable()
         : CancelableRunnable(
               "gfxPlatformFontList::InitOtherFamilyNamesRunnable"),
           mIsCanceled(false) {}
@@ -482,17 +481,17 @@ class gfxPlatformFontList : public gfxFo
   // read the loader initialization prefs, and start it
   void GetPrefsAndStartLoader();
 
   // for font list changes that affect all documents
   void ForceGlobalReflow() { gfxPlatform::ForceGlobalReflow(); }
 
   void RebuildLocalFonts();
 
-  void ResolveGenericFontNames(mozilla::StyleGenericFontFamily aGenericType,
+  void ResolveGenericFontNames(mozilla::FontFamilyType aGenericType,
                                eFontPrefLang aPrefLang,
                                PrefFontList* aGenericFamilies);
 
   void ResolveEmojiFontNames(PrefFontList* aGenericFamilies);
 
   void GetFontFamiliesFromGenericFamilies(nsTArray<nsCString>& aGenericFamilies,
                                           nsAtom* aLangGroup,
                                           PrefFontList* aFontFamilies);
@@ -548,19 +547,18 @@ class gfxPlatformFontList : public gfxFo
 
   // face names missed when face name loading takes a long time
   mozilla::UniquePtr<nsTHashtable<nsCStringHashKey>> mFaceNamesMissed;
 
   // localized family names missed when face name loading takes a long time
   mozilla::UniquePtr<nsTHashtable<nsCStringHashKey>> mOtherNamesMissed;
 
   typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>,
-                               size_t(mozilla::StyleGenericFontFamily::None),
-                               size_t(
-                                   mozilla::StyleGenericFontFamily::MozEmoji)>
+                               mozilla::eFamily_generic_first,
+                               mozilla::eFamily_generic_count>
       PrefFontsForLangGroup;
   mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First,
                        eFontPrefLang_Count>
       mLangGroupPrefFonts;
   mozilla::UniquePtr<PrefFontList> mEmojiPrefFont;
 
   // when system-wide font lookup fails for a character, cache it to skip future
   // searches
@@ -586,16 +584,16 @@ class gfxPlatformFontList : public gfxFo
   // see bugs 636957, 1070983, 1189129
   uint32_t mFontlistInitCount;  // num times InitFontList called
 
   nsTHashtable<nsPtrHashKey<gfxUserFontSet>> mUserFontSetList;
 
   nsLanguageAtomService* mLangService;
 
   nsTArray<uint32_t> mCJKPrefLangs;
-  nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup;
+  nsTArray<mozilla::FontFamilyType> mDefaultGenericsLangGroup;
 
   bool mFontFamilyWhitelistActive;
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags)
 
 #endif /* GFXPLATFORMFONTLIST_H_ */
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -1530,17 +1530,17 @@ void gfxTextRun::SetSpaceGlyph(gfxFont* 
   bool vertical =
       !!(GetFlags() & gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT);
   gfxFontShaper::RoundingFlags roundingFlags =
       aFont->GetRoundOffsetsToPixels(aDrawTarget);
   gfxShapedWord* sw = aFont->GetShapedWord(
       aDrawTarget, &space, 1, gfxShapedWord::HashMix(0, ' '), Script::LATIN,
       vertical, mAppUnitsPerDevUnit, flags, roundingFlags, nullptr);
   if (sw) {
-    AddGlyphRun(aFont, FontMatchType::Kind::kFontGroup, aCharIndex, false,
+    AddGlyphRun(aFont, FontMatchType::kFontGroup, aCharIndex, false,
                 aOrientation);
     CopyGlyphDataFrom(sw, aCharIndex);
     GetCharacterGlyphs()[aCharIndex].SetIsSpace();
   }
 }
 
 bool gfxTextRun::SetSpaceGlyphIfSimple(gfxFont* aFont, uint32_t aCharIndex,
                                        char16_t aSpaceChar,
@@ -1555,17 +1555,17 @@ bool gfxTextRun::SetSpaceGlyphIfSimple(g
           ? nsFontMetrics::eVertical
           : nsFontMetrics::eHorizontal;
   uint32_t spaceWidthAppUnits = NS_lroundf(
       aFont->GetMetrics(fontOrientation).spaceWidth * mAppUnitsPerDevUnit);
   if (!CompressedGlyph::IsSimpleAdvance(spaceWidthAppUnits)) {
     return false;
   }
 
-  AddGlyphRun(aFont, FontMatchType::Kind::kFontGroup, aCharIndex, false,
+  AddGlyphRun(aFont, FontMatchType::kFontGroup, aCharIndex, false,
               aOrientation);
   CompressedGlyph g =
       CompressedGlyph::MakeSimpleGlyph(spaceWidthAppUnits, spaceGlyph);
   if (aSpaceChar == ' ') {
     g.SetIsSpace();
   }
   GetCharacterGlyphs()[aCharIndex] = g;
   return true;
@@ -1710,25 +1710,25 @@ void gfxFontGroup::BuildFontList() {
   for (const FontFamilyName& name : mFamilyList.GetFontlist()->mNames) {
     if (name.IsNamed()) {
       if (name.mName) {
         AddPlatformFont(nsAtomCString(name.mName), fonts);
       } else {
         MOZ_ASSERT_UNREACHABLE("broken FontFamilyName, no atom!");
       }
     } else {
-      pfl->AddGenericFonts(name.mGeneric, mStyle.language, fonts);
+      pfl->AddGenericFonts(name.mType, mStyle.language, fonts);
       if (mTextPerf) {
         mTextPerf->current.genericLookups++;
       }
     }
   }
 
   // if necessary, append default generic onto the end
-  if (mFamilyList.GetDefaultFontType() != StyleGenericFontFamily::None &&
+  if (mFamilyList.GetDefaultFontType() != eFamily_none &&
       !mFamilyList.HasDefaultGeneric()) {
     pfl->AddGenericFonts(mFamilyList.GetDefaultFontType(), mStyle.language,
                          fonts);
     if (mTextPerf) {
       mTextPerf->current.genericLookups++;
     }
   }
 
@@ -1756,17 +1756,17 @@ void gfxFontGroup::AddPlatformFont(const
 
   // Not known in the user font set ==> check system fonts
   gfxPlatformFontList::PlatformFontList()->FindAndAddFamilies(
       aName, &aFamilyList, gfxPlatformFontList::FindFamiliesFlags(0), &mStyle,
       mDevToCssSize);
 }
 
 void gfxFontGroup::AddFamilyToFontList(gfxFontFamily* aFamily,
-                                       StyleGenericFontFamily aGeneric) {
+                                       FontFamilyType aGeneric) {
   if (!aFamily) {
     MOZ_ASSERT_UNREACHABLE("don't try to add a null font family!");
     return;
   }
   AutoTArray<gfxFontEntry*, 4> fontEntryList;
   aFamily->FindAllFontsForStyle(mStyle, fontEntryList);
   // add these to the fontlist
   for (gfxFontEntry* fe : fontEntryList) {
@@ -1958,17 +1958,17 @@ gfxFont* gfxFontGroup::GetDefaultFont() 
                    familiesString.get());
     MOZ_CRASH_UNSAFE(msg);
   }
 
   return mDefaultFont.get();
 }
 
 gfxFont* gfxFontGroup::GetFirstValidFont(uint32_t aCh,
-                                         StyleGenericFontFamily* aGeneric) {
+                                         FontFamilyType* aGeneric) {
   uint32_t count = mFonts.Length();
   for (uint32_t i = 0; i < count; ++i) {
     FamilyFace& ff = mFonts[i];
     if (ff.IsInvalid()) {
       continue;
     }
 
     // already have a font?
@@ -2001,17 +2001,17 @@ gfxFont* gfxFontGroup::GetFirstValidFont
     if (font) {
       if (aGeneric) {
         *aGeneric = mFonts[i].Generic();
       }
       return font;
     }
   }
   if (aGeneric) {
-    *aGeneric = StyleGenericFontFamily::None;
+    *aGeneric = eFamily_none;
   }
   return GetDefaultFont();
 }
 
 gfxFont* gfxFontGroup::GetFirstMathFont() {
   uint32_t count = mFonts.Length();
   for (uint32_t i = 0; i < count; ++i) {
     gfxFont* font = GetFontAt(i);
@@ -2073,17 +2073,17 @@ already_AddRefed<gfxTextRun> gfxFontGrou
   }
 
   gfxFont* font = GetFirstValidFont();
   if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
       MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
     // Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
     // them, and always create at least size 1 fonts, i.e. they still
     // render something for size 0 fonts.
-    textRun->AddGlyphRun(font, FontMatchType::Kind::kFontGroup, 0, false,
+    textRun->AddGlyphRun(font, FontMatchType::kFontGroup, 0, false,
                          orientation);
   } else {
     if (font->GetSpaceGlyph()) {
       // Normally, the font has a cached space glyph, so we can avoid
       // the cost of calling FindFontForChar.
       textRun->SetSpaceGlyph(font, aParams->mDrawTarget, 0, orientation);
     } else {
       // In case the primary font doesn't have <space> (bug 970891),
@@ -2111,18 +2111,18 @@ already_AddRefed<gfxTextRun> gfxFontGrou
   if (!textRun) {
     return nullptr;
   }
 
   gfx::ShapedTextFlags orientation = aFlags & ShapedTextFlags::TEXT_ORIENT_MASK;
   if (orientation == ShapedTextFlags::TEXT_ORIENT_VERTICAL_MIXED) {
     orientation = ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT;
   }
-  textRun->AddGlyphRun(GetFirstValidFont(), FontMatchType::Kind::kFontGroup, 0,
-                       false, orientation);
+  textRun->AddGlyphRun(GetFirstValidFont(), FontMatchType::kFontGroup, 0, false,
+                       orientation);
   return textRun.forget();
 }
 
 already_AddRefed<gfxTextRun> gfxFontGroup::MakeHyphenTextRun(
     DrawTarget* aDrawTarget, uint32_t aAppUnitsPerDevUnit) {
   // only use U+2010 if it is supported by the first font in the group;
   // it's better to use ASCII '-' from the primary font than to fall back to
   // U+2010 from some other, possibly poorly-matching face
@@ -2269,20 +2269,19 @@ void gfxFontGroup::InitTextRun(DrawTarge
         nsAutoString styleString;
         nsStyleUtil::AppendFontSlantStyle(mStyle.style, styleString);
         MOZ_LOG(
             log, LogLevel::Warning,
             ("(%s) fontgroup: [%s] default: %s lang: %s script: %d "
              "len %d weight: %g stretch: %g%% style: %s size: %6.2f %zu-byte "
              "TEXTRUN [%s] ENDTEXTRUN\n",
              (mStyle.systemFont ? "textrunui" : "textrun"), families.get(),
-             (mFamilyList.GetDefaultFontType() == StyleGenericFontFamily::Serif
+             (mFamilyList.GetDefaultFontType() == eFamily_serif
                   ? "serif"
-                  : (mFamilyList.GetDefaultFontType() ==
-                             StyleGenericFontFamily::SansSerif
+                  : (mFamilyList.GetDefaultFontType() == eFamily_sans_serif
                          ? "sans-serif"
                          : "none")),
              lang.get(), static_cast<int>(Script::LATIN), aLength,
              mStyle.weight.ToFloat(), mStyle.stretch.Percentage(),
              NS_ConvertUTF16toUTF8(styleString).get(), mStyle.size, sizeof(T),
              str.get()));
       }
 
@@ -2316,21 +2315,19 @@ void gfxFontGroup::InitTextRun(DrawTarge
           nsStyleUtil::AppendFontSlantStyle(mStyle.style, styleString);
           uint32_t runLen = runLimit - runStart;
           MOZ_LOG(
               log, LogLevel::Warning,
               ("(%s) fontgroup: [%s] default: %s lang: %s script: %d "
                "len %d weight: %g stretch: %g%% style: %s size: %6.2f "
                "%zu-byte TEXTRUN [%s] ENDTEXTRUN\n",
                (mStyle.systemFont ? "textrunui" : "textrun"), families.get(),
-               (mFamilyList.GetDefaultFontType() ==
-                        StyleGenericFontFamily::Serif
+               (mFamilyList.GetDefaultFontType() == eFamily_serif
                     ? "serif"
-                    : (mFamilyList.GetDefaultFontType() ==
-                               StyleGenericFontFamily::SansSerif
+                    : (mFamilyList.GetDefaultFontType() == eFamily_sans_serif
                            ? "sans-serif"
                            : "none")),
                lang.get(), static_cast<int>(runScript), runLen,
                mStyle.weight.ToFloat(), mStyle.stretch.Percentage(),
                NS_ConvertUTF16toUTF8(styleString).get(), mStyle.size, sizeof(T),
                NS_ConvertUTF16toUTF8(textPtr + runStart, runLen).get()));
         }
 
@@ -2498,17 +2495,17 @@ void gfxFontGroup::InitScriptRun(DrawTar
         if (!matchedFont->SplitAndInitTextRun(
                 aDrawTarget, aTextRun, aString + runStart, aOffset + runStart,
                 matchedLength, aRunScript, range.orientation)) {
           // glyph layout failed! treat as missing glyphs
           matchedFont = nullptr;
         }
       }
     } else {
-      aTextRun->AddGlyphRun(mainFont, FontMatchType::Kind::kFontGroup,
+      aTextRun->AddGlyphRun(mainFont, FontMatchType::kFontGroup,
                             aOffset + runStart, (matchedLength > 0),
                             range.orientation);
     }
 
     if (!matchedFont) {
       // We need to set cluster boundaries (and mark spaces) so that
       // surrogate pairs, combining characters, etc behave properly,
       // even if we don't have glyphs for them
@@ -2705,32 +2702,34 @@ gfxFont* gfxFontGroup::FindFontForChar(u
   bool isJoinControl = gfxFontUtils::IsJoinControl(aCh);
   bool wasJoinCauser = gfxFontUtils::IsJoinCauser(aPrevCh);
   bool isVarSelector = gfxFontUtils::IsVarSelector(aCh);
 
   if (!isJoinControl && !wasJoinCauser && !isVarSelector) {
     gfxFont* firstFont = GetFontAt(0, aCh);
     if (firstFont) {
       if (firstFont->HasCharacter(aCh)) {
-        *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()};
+        *aMatchType =
+            FontMatchType::kFontGroup | FontMatchType(mFonts[0].Generic());
         return firstFont;
       }
 
       gfxFont* font = nullptr;
       if (mFonts[0].CheckForFallbackFaces()) {
         font = FindFallbackFaceForChar(mFonts[0].Family(), aCh);
       } else if (!firstFont->GetFontEntry()->IsUserFont()) {
         // For platform fonts (but not userfonts), we may need to do
         // fallback within the family to handle cases where some faces
         // such as Italic or Black have reduced character sets compared
         // to the family's Regular face.
         font = FindFallbackFaceForChar(mFonts[0].Family(), aCh);
       }
       if (font) {
-        *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()};
+        *aMatchType =
+            FontMatchType::kFontGroup | FontMatchType(mFonts[0].Generic());
         return font;
       }
     }
 
     // we don't need to check the first font again below
     ++nextIndex;
   }
 
@@ -2770,17 +2769,17 @@ gfxFont* gfxFontGroup::FindFontForChar(u
     if (ff.IsInvalid() || ff.IsLoading()) {
       continue;
     }
 
     // if available, use already made gfxFont and check for character
     gfxFont* font = ff.Font();
     if (font) {
       if (font->HasCharacter(aCh)) {
-        *aMatchType = {FontMatchType::Kind::kFontGroup, ff.Generic()};
+        *aMatchType = FontMatchType::kFontGroup | FontMatchType(ff.Generic());
         return font;
       }
       continue;
     }
 
     // don't have a gfxFont yet, test before building
     gfxFontEntry* fe = ff.FontEntry();
     if (fe->mIsUserFontContainer) {
@@ -2799,94 +2798,96 @@ gfxFont* gfxFontGroup::FindFontForChar(u
           !mSkipDrawing && !FontLoadingForFamily(ff.Family(), aCh)) {
         ufe->Load();
         ff.CheckState(mSkipDrawing);
       }
       gfxFontEntry* pfe = ufe->GetPlatformFontEntry();
       if (pfe && pfe->HasCharacter(aCh)) {
         font = GetFontAt(i, aCh);
         if (font) {
-          *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[i].Generic()};
+          *aMatchType =
+              FontMatchType::kFontGroup | FontMatchType(mFonts[i].Generic());
           return font;
         }
       }
     } else if (fe->HasCharacter(aCh)) {
       // for normal platform fonts, after checking the cmap
       // build the font via GetFontAt
       font = GetFontAt(i, aCh);
       if (font) {
-        *aMatchType = {FontMatchType::Kind::kFontGroup, mFonts[i].Generic()};
+        *aMatchType =
+            FontMatchType::kFontGroup | FontMatchType(mFonts[i].Generic());
         return font;
       }
     }
 
     // check other family faces if needed
     if (ff.CheckForFallbackFaces()) {
       NS_ASSERTION(i == 0 ? true
                           : !mFonts[i - 1].CheckForFallbackFaces() ||
                                 !mFonts[i - 1].Family()->Name().Equals(
                                     ff.Family()->Name()),
                    "should only do fallback once per font family");
       font = FindFallbackFaceForChar(ff.Family(), aCh);
       if (font) {
-        *aMatchType = {FontMatchType::Kind::kFontGroup, ff.Generic()};
+        *aMatchType = FontMatchType::kFontGroup | FontMatchType(ff.Generic());
         return font;
       }
     } else {
       // For platform fonts, but not user fonts, consider intra-family
       // fallback to handle styles with reduced character sets (see
       // also above).
       fe = ff.FontEntry();
       if (!fe->mIsUserFontContainer && !fe->IsUserFont()) {
         font = FindFallbackFaceForChar(ff.Family(), aCh);
         if (font) {
-          *aMatchType = {FontMatchType::Kind::kFontGroup, ff.Generic()};
+          *aMatchType = FontMatchType::kFontGroup | FontMatchType(ff.Generic());
           return font;
         }
       }
     }
   }
 
   if (fontListLength == 0) {
     gfxFont* defaultFont = GetDefaultFont();
     if (defaultFont->HasCharacter(aCh)) {
-      *aMatchType = FontMatchType::Kind::kFontGroup;
+      *aMatchType = FontMatchType::kFontGroup;
       return defaultFont;
     }
   }
 
   // if character is in Private Use Area, don't do matching against pref or
   // system fonts
   if ((aCh >= 0xE000 && aCh <= 0xF8FF) || (aCh >= 0xF0000 && aCh <= 0x10FFFD))
     return nullptr;
 
   // 2. search pref fonts
   gfxFont* font = WhichPrefFontSupportsChar(aCh, aNextCh);
   if (font) {
-    *aMatchType = FontMatchType::Kind::kPrefsFallback;
+    *aMatchType = FontMatchType::kPrefsFallback;
     return font;
   }
 
   // 3. use fallback fonts
   // -- before searching for something else check the font used for the
   //    previous character
   if (aPrevMatchedFont && aPrevMatchedFont->HasCharacter(aCh)) {
-    *aMatchType = FontMatchType::Kind::kSystemFallback;
+    *aMatchType = FontMatchType::kSystemFallback;
     return aPrevMatchedFont;
   }
 
   // for known "space" characters, don't do a full system-fallback search;
   // we'll synthesize appropriate-width spaces instead of missing-glyph boxes
   if (GetGeneralCategory(aCh) == HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR &&
       GetFirstValidFont()->SynthesizeSpaceWidth(aCh) >= 0.0) {
     return nullptr;
   }
 
   // -- otherwise look for other stuff
-  *aMatchType = FontMatchType::Kind::kSystemFallback;
+  *aMatchType = FontMatchType::kSystemFallback;
   return WhichSystemFontSupportsChar(aCh, aNextCh, aRunScript);
 }
 
 template <typename T>
 void gfxFontGroup::ComputeRanges(nsTArray<TextRange>& aRanges, const T* aString,
                                  uint32_t aLength, Script aRunScript,
                                  gfx::ShapedTextFlags aOrientation) {
   NS_ASSERTION(aRanges.Length() == 0, "aRanges must be initially empty");
@@ -2900,22 +2901,22 @@ void gfxFontGroup::ComputeRanges(nsTArra
       nextCh = SURROGATE_TO_UCS4(nextCh, aString[1]);
     }
   }
   int32_t lastRangeIndex = -1;
 
   // initialize prevFont to the group's primary font, so that this will be
   // used for string-initial control chars, etc rather than risk hitting font
   // fallback for these (bug 716229)
-  StyleGenericFontFamily generic = StyleGenericFontFamily::None;
+  FontFamilyType generic = eFamily_none;
   gfxFont* prevFont = GetFirstValidFont(' ', &generic);
 
   // if we use the initial value of prevFont, we treat this as a match from
   // the font group; fixes bug 978313
-  FontMatchType matchType = {FontMatchType::Kind::kFontGroup, generic};
+  FontMatchType matchType = FontMatchType::kFontGroup | FontMatchType(generic);
 
   for (uint32_t i = 0; i < aLength; i++) {
     const uint32_t origI = i;  // save off in case we increase for surrogate
 
     // set up current ch
     uint32_t ch = nextCh;
 
     // Get next char (if any) so that FindFontForChar can look ahead
@@ -2952,27 +2953,28 @@ void gfxFontGroup::ComputeRanges(nsTArra
     // the special cases where FindFontForChar will attempt to propagate
     // the font selected for an adjacent character.
     if ((font = GetFontAt(0, ch)) != nullptr && font->HasCharacter(ch) &&
         (sizeof(T) == sizeof(uint8_t) ||
          (!IsClusterExtender(ch) && ch != NARROW_NO_BREAK_SPACE &&
           !gfxFontUtils::IsJoinControl(ch) &&
           !gfxFontUtils::IsJoinCauser(prevCh) &&
           !gfxFontUtils::IsVarSelector(ch)))) {
-      matchType = {FontMatchType::Kind::kFontGroup, mFonts[0].Generic()};
+      matchType =
+          FontMatchType::kFontGroup | FontMatchType(mFonts[0].Generic());
     } else {
       font =
           FindFontForChar(ch, prevCh, nextCh, aRunScript, prevFont, &matchType);
     }
 
 #ifndef RELEASE_OR_BETA
     if (MOZ_UNLIKELY(mTextPerf)) {
-      if (matchType.kind == FontMatchType::Kind::kPrefsFallback) {
+      if (matchType & FontMatchType::kPrefsFallback) {
         mTextPerf->current.fallbackPrefs++;
-      } else if (matchType.kind == FontMatchType::Kind::kSystemFallback) {
+      } else if (matchType & FontMatchType::kSystemFallback) {
         mTextPerf->current.fallbackSystem++;
       }
     }
 #endif
 
     prevCh = ch;
 
     ShapedTextFlags orient = aOrientation;
@@ -3044,44 +3046,43 @@ void gfxFontGroup::ComputeRanges(nsTArra
     nsAutoCString families;
     mFamilyList.ToString(families);
 
     // collect the font matched for each range
     nsAutoCString fontMatches;
     for (size_t i = 0, i_end = aRanges.Length(); i < i_end; i++) {
       const TextRange& r = aRanges[i];
       nsAutoCString matchTypes;
-      if (r.matchType.kind & FontMatchType::Kind::kFontGroup) {
+      if (r.matchType & FontMatchType::kFontGroup) {
         matchTypes.AppendLiteral("list");
       }
-      if (r.matchType.kind & FontMatchType::Kind::kPrefsFallback) {
+      if (r.matchType & FontMatchType::kPrefsFallback) {
         if (!matchTypes.IsEmpty()) {
           matchTypes.AppendLiteral(",");
         }
         matchTypes.AppendLiteral("prefs");
       }
-      if (r.matchType.kind & FontMatchType::Kind::kPrefsFallback) {
+      if (r.matchType & FontMatchType::kPrefsFallback) {
         if (!matchTypes.IsEmpty()) {
           matchTypes.AppendLiteral(",");
         }
         matchTypes.AppendLiteral("sys");
       }
       fontMatches.AppendPrintf(
           " [%u:%u] %.200s (%s)", r.start, r.end,
           (r.font.get() ? r.font->GetName().get() : "<null>"),
           matchTypes.get());
     }
     MOZ_LOG(log, LogLevel::Debug,
             ("(%s-fontmatching) fontgroup: [%s] default: %s lang: %s script: %d"
              "%s\n",
              (mStyle.systemFont ? "textrunui" : "textrun"), families.get(),
-             (mFamilyList.GetDefaultFontType() == StyleGenericFontFamily::Serif
+             (mFamilyList.GetDefaultFontType() == eFamily_serif
                   ? "serif"
-                  : (mFamilyList.GetDefaultFontType() ==
-                             StyleGenericFontFamily::SansSerif
+                  : (mFamilyList.GetDefaultFontType() == eFamily_sans_serif
                          ? "sans-serif"
                          : "none")),
              lang.get(), static_cast<int>(aRunScript), fontMatches.get()));
   }
 #endif
 }
 
 gfxUserFontSet* gfxFontGroup::GetUserFontSet() { return mUserFontSet; }
@@ -3169,17 +3170,18 @@ gfxFont* gfxFontGroup::WhichPrefFontSupp
   // based on char lang and page lang, set up list of pref lang fonts to check
   eFontPrefLang prefLangs[kMaxLenPrefLangList];
   uint32_t i, numLangs = 0;
 
   pfl->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang);
 
   for (i = 0; i < numLangs; i++) {
     eFontPrefLang currentLang = prefLangs[i];
-    StyleGenericFontFamily defaultGeneric = pfl->GetDefaultGeneric(currentLang);
+    mozilla::FontFamilyType defaultGeneric =
+        pfl->GetDefaultGeneric(currentLang);
     gfxPlatformFontList::PrefFontList* families =
         pfl->GetPrefFontsLangGroup(defaultGeneric, currentLang);
     NS_ASSERTION(families, "no pref font families found");
 
     // find the first pref font that includes the character
     uint32_t j, numPrefs;
     numPrefs = families->Length();
     for (j = 0; j < numPrefs; j++) {
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -846,18 +846,18 @@ class gfxFontGroup final : public gfxTex
                gfxUserFontSet* aUserFontSet, gfxFloat aDevToCssSize);
 
   virtual ~gfxFontGroup();
 
   // Returns first valid font in the fontlist or default font.
   // Initiates userfont loads if userfont not loaded.
   // aGeneric: if non-null, returns the CSS generic type that was mapped to
   //           this font
-  gfxFont* GetFirstValidFont(
-      uint32_t aCh = 0x20, mozilla::StyleGenericFontFamily* aGeneric = nullptr);
+  gfxFont* GetFirstValidFont(uint32_t aCh = 0x20,
+                             mozilla::FontFamilyType* aGeneric = nullptr);
 
   // Returns the first font in the font-group that has an OpenType MATH table,
   // or null if no such font is available. The GetMathConstant methods may be
   // called on the returned font.
   gfxFont* GetFirstMathFont();
 
   const gfxFontStyle* GetStyle() const { return &mStyle; }
 
@@ -1019,39 +1019,39 @@ class gfxFontGroup final : public gfxTex
                      uint32_t aLength, Script aRunScript,
                      mozilla::gfx::ShapedTextFlags aOrientation);
 
   class FamilyFace {
    public:
     FamilyFace()
         : mFamily(nullptr),
           mFontEntry(nullptr),
-          mGeneric(mozilla::StyleGenericFontFamily::None),
+          mGeneric(mozilla::eFamily_none),
           mFontCreated(false),
           mLoading(false),
           mInvalid(false),
           mCheckForFallbackFaces(false) {}
 
     FamilyFace(gfxFontFamily* aFamily, gfxFont* aFont,
-               mozilla::StyleGenericFontFamily aGeneric)
+               mozilla::FontFamilyType aGeneric)
         : mFamily(aFamily),
           mGeneric(aGeneric),
           mFontCreated(true),
           mLoading(false),
           mInvalid(false),
           mCheckForFallbackFaces(false) {
       NS_ASSERTION(aFont, "font pointer must not be null");
       NS_ASSERTION(!aFamily || aFamily->ContainsFace(aFont->GetFontEntry()),
                    "font is not a member of the given family");
       mFont = aFont;
       NS_ADDREF(aFont);
     }
 
     FamilyFace(gfxFontFamily* aFamily, gfxFontEntry* aFontEntry,
-               mozilla::StyleGenericFontFamily aGeneric)
+               mozilla::FontFamilyType aGeneric)
         : mFamily(aFamily),
           mGeneric(aGeneric),
           mFontCreated(false),
           mLoading(false),
           mInvalid(false),
           mCheckForFallbackFaces(false) {
       NS_ASSERTION(aFontEntry, "font entry pointer must not be null");
       NS_ASSERTION(!aFamily || aFamily->ContainsFace(aFontEntry),
@@ -1110,17 +1110,17 @@ class gfxFontGroup final : public gfxTex
 
     gfxFontFamily* Family() const { return mFamily.get(); }
     gfxFont* Font() const { return mFontCreated ? mFont : nullptr; }
 
     gfxFontEntry* FontEntry() const {
       return mFontCreated ? mFont->GetFontEntry() : mFontEntry;
     }
 
-    mozilla::StyleGenericFontFamily Generic() const { return mGeneric; }
+    mozilla::FontFamilyType Generic() const { return mGeneric; }
 
     bool IsUserFontContainer() const {
       return FontEntry()->mIsUserFontContainer;
     }
     bool IsLoading() const { return mLoading; }
     bool IsInvalid() const { return mInvalid; }
     void CheckState(bool& aSkipDrawing);
     void SetLoading(bool aIsLoading) { mLoading = aIsLoading; }
@@ -1147,17 +1147,17 @@ class gfxFontGroup final : public gfxTex
     RefPtr<gfxFontFamily> mFamily;
     // either a font or a font entry exists
     union {
       // Whichever of these fields is actually present will be a strong
       // reference, with refcounting handled manually.
       gfxFont* MOZ_OWNING_REF mFont;
       gfxFontEntry* MOZ_OWNING_REF mFontEntry;
     };
-    mozilla::StyleGenericFontFamily mGeneric;
+    mozilla::FontFamilyType mGeneric;
     bool mFontCreated : 1;
     bool mLoading : 1;
     bool mInvalid : 1;
     bool mCheckForFallbackFaces : 1;
   };
 
   // List of font families, either named or generic.
   // Generic names map to system pref fonts based on language.
@@ -1256,17 +1256,17 @@ class gfxFontGroup final : public gfxTex
   // helper methods for looking up fonts
 
   // lookup and add a font with a given name (i.e. *not* a generic!)
   void AddPlatformFont(const nsACString& aName,
                        nsTArray<FamilyAndGeneric>& aFamilyList);
 
   // do style selection and add entries to list
   void AddFamilyToFontList(gfxFontFamily* aFamily,
-                           mozilla::StyleGenericFontFamily aGeneric);
+                           mozilla::FontFamilyType aGeneric);
 };
 
 // A "missing font recorder" is to be used during text-run creation to keep
 // a record of any scripts encountered for which font coverage was lacking;
 // when Flush() is called, it sends a notification that front-end code can use
 // to download fonts on demand (or whatever else it wants to do).
 
 #define GFX_MISSING_FONTS_NOTIFY_PREF "gfx.missing_fonts.notify"
--- a/gfx/thebes/gfxTypes.h
+++ b/gfx/thebes/gfxTypes.h
@@ -3,17 +3,16 @@
  * 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/. */
 
 #ifndef GFX_TYPES_H
 #define GFX_TYPES_H
 
 #include <stdint.h>
 #include "mozilla/TypedEnumBits.h"
-#include "nsStyleConsts.h"
 
 typedef struct _cairo_surface cairo_surface_t;
 typedef struct _cairo_user_data_key cairo_user_data_key_t;
 
 typedef void (*thebes_destroy_func_t)(void *data);
 
 /**
  * Currently needs to be 'double' for Cairo compatibility. Could
@@ -83,47 +82,24 @@ enum class gfxAlphaType {
   Premult,
   NonPremult,
 };
 
 /**
  * Type used to record how a particular font is selected during the font-
  * matching process, so that this can be exposed to the Inspector.
  */
-struct FontMatchType {
-  enum class Kind : uint8_t {
-    kFontGroup = 1,
-    kPrefsFallback = 1 << 1,
-    kSystemFallback = 1 << 2,
-  };
-
-  inline FontMatchType& operator|=(const FontMatchType& aOther);
-
-  bool operator==(const FontMatchType& aOther) const {
-    return kind == aOther.kind && generic == aOther.generic;
-  }
+enum class FontMatchType : uint16_t {
+  // The CSS generic that mapped to this font, if any. This field of
+  // the MatchType stores a FontFamilyType value as defined in the enum
+  // in gfxFontFamilyList.h.
+  kGenericMask = 0x00ff,
 
-  bool operator!=(const FontMatchType& aOther) const {
-    return !(*this == aOther);
-  }
-
-  MOZ_IMPLICIT FontMatchType() = default;
-  MOZ_IMPLICIT FontMatchType(Kind aKind) : kind(aKind) {}
-  FontMatchType(Kind aKind, mozilla::StyleGenericFontFamily aGeneric)
-      : kind(aKind), generic(aGeneric) {}
-
-  Kind kind = static_cast<Kind>(0);
-  mozilla::StyleGenericFontFamily generic =
-      mozilla::StyleGenericFontFamily::None;
+  // Flags for recording the kind of font-matching that was used.
+  // Note that multiple flags may be set on a single range.
+  kFontGroup = 0x0100,
+  kPrefsFallback = 0x0200,
+  kSystemFallback = 0x0400
 };
 
-MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(FontMatchType::Kind)
-
-FontMatchType& FontMatchType::operator|=(const FontMatchType& aOther) {
-  kind |= aOther.kind;
-  // We only keep track of one generic.
-  if (generic != aOther.generic) {
-    generic = mozilla::StyleGenericFontFamily::None;
-  }
-  return *this;
-}
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(FontMatchType)
 
 #endif /* GFX_TYPES_H */
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -10202,18 +10202,17 @@ void ReflowCountMgr::PaintCount(const ch
       gfxPoint devPixelOffset =
           nsLayoutUtils::PointToGfxPoint(aOffset, appUnitsPerDevPixel);
       aRenderingContext->SetMatrixDouble(
           aRenderingContext->CurrentMatrixDouble().PreTranslate(
               devPixelOffset));
 
       // We don't care about the document language or user fonts here;
       // just get a default Latin font.
-      nsFont font(StyleGenericFontFamily::Serif,
-                  nsPresContext::CSSPixelsToAppUnits(11));
+      nsFont font(eFamily_serif, nsPresContext::CSSPixelsToAppUnits(11));
       nsFontMetrics::Params params;
       params.language = nsGkAtoms::x_western;
       params.textPerf = aPresContext->GetTextPerfMetrics();
       params.featureValueLookup = aPresContext->GetFontFeatureValuesLookup();
       RefPtr<nsFontMetrics> fm =
           aPresContext->DeviceContext()->GetMetricsFor(font, params);
 
       char buf[16];
--- a/layout/base/StaticPresData.cpp
+++ b/layout/base/StaticPresData.cpp
@@ -35,27 +35,29 @@ StaticPresData::StaticPresData() {
 
 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
   _pref.Assign(_s0);                        \
   _pref.Append(_s1);
 
 // clang-format off
 static const char* const kGenericFont[] = {
   ".variable.",
+  ".fixed.",
   ".serif.",
   ".sans-serif.",
   ".monospace.",
   ".cursive.",
   ".fantasy."
 };
 // clang-format on
 
 // These are private, use the list in nsFont.h if you want a public list.
 enum {
   eDefaultFont_Variable,
+  eDefaultFont_Fixed,
   eDefaultFont_Serif,
   eDefaultFont_SansSerif,
   eDefaultFont_Monospace,
   eDefaultFont_Cursive,
   eDefaultFont_Fantasy,
   eDefaultFont_COUNT
 };
 
@@ -86,30 +88,31 @@ void LangGroupFontPrefs::Initialize(nsSt
   font.minimum-size.[langGroup] = integer
     settable by the user
   */
 
   nsAutoCString langGroup;
   aLangGroupAtom->ToUTF8String(langGroup);
 
   mDefaultVariableFont.size = nsPresContext::CSSPixelsToAppUnits(16);
-  mDefaultMonospaceFont.size = nsPresContext::CSSPixelsToAppUnits(13);
+  mDefaultFixedFont.size = nsPresContext::CSSPixelsToAppUnits(13);
 
   nsAutoCString pref;
 
   // get font.minimum-size.[langGroup]
 
   MAKE_FONT_PREF_KEY(pref, "font.minimum-size.", langGroup);
 
   int32_t size = Preferences::GetInt(pref.get());
   mMinimumFontSize = nsPresContext::CSSPixelsToAppUnits(size);
 
   // clang-format off
   nsFont* fontTypes[] = {
     &mDefaultVariableFont,
+    &mDefaultFixedFont,
     &mDefaultSerifFont,
     &mDefaultSansSerifFont,
     &mDefaultMonospaceFont,
     &mDefaultCursiveFont,
     &mDefaultFantasyFont
   };
   // clang-format on
   static_assert(MOZ_ARRAY_LENGTH(fontTypes) == eDefaultFont_COUNT,
@@ -133,43 +136,50 @@ void LangGroupFontPrefs::Initialize(nsSt
     if (eType == eDefaultFont_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()) {
         FontFamilyName defaultVariableName = FontFamilyName::Convert(value);
-        StyleGenericFontFamily defaultType = defaultVariableName.mGeneric;
-        NS_ASSERTION(defaultType == StyleGenericFontFamily::Serif ||
-                         defaultType == StyleGenericFontFamily::SansSerif,
-                     "default type must be serif or sans-serif");
+        FontFamilyType defaultType = defaultVariableName.mType;
+        NS_ASSERTION(
+            defaultType == eFamily_serif || defaultType == eFamily_sans_serif,
+            "default type must be serif or sans-serif");
         mDefaultVariableFont.fontlist = FontFamilyList();
         mDefaultVariableFont.fontlist.SetDefaultFontType(defaultType);
         // 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.
       } else {
         MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup);
         Preferences::GetCString(pref.get(), value);
         if (!value.IsEmpty()) {
           FontFamilyName defaultVariableName = FontFamilyName::Convert(value);
-          StyleGenericFontFamily defaultType = defaultVariableName.mGeneric;
-          NS_ASSERTION(defaultType == StyleGenericFontFamily::Serif ||
-                           defaultType == StyleGenericFontFamily::SansSerif,
-                       "default type must be serif or sans-serif");
+          FontFamilyType defaultType = defaultVariableName.mType;
+          NS_ASSERTION(
+              defaultType == eFamily_serif || defaultType == eFamily_sans_serif,
+              "default type must be serif or sans-serif");
           mDefaultVariableFont.fontlist = FontFamilyList();
           mDefaultVariableFont.fontlist.SetDefaultFontType(defaultType);
           // 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.
         }
       }
     } else {
-      if (eType != eDefaultFont_Monospace) {
+      if (eType == eDefaultFont_Monospace) {
+        // This takes care of the confusion whereby people often expect
+        // "monospace" to have the same default font-size as "-moz-fixed" (this
+        // tentative size may be overwritten with the specific value for
+        // "monospace" when "font.size.monospace.[langGroup]" is read -- see
+        // below)
+        mDefaultMonospaceFont.size = mDefaultFixedFont.size;
+      } else if (eType != eDefaultFont_Fixed) {
         // 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
--- a/layout/base/StaticPresData.h
+++ b/layout/base/StaticPresData.h
@@ -17,23 +17,23 @@
 namespace mozilla {
 
 struct LangGroupFontPrefs {
   // Font sizes default to zero; they will be set in GetFontPreferences
   LangGroupFontPrefs()
       : mLangGroup(nullptr),
         mMinimumFontSize(0),
         mDefaultVariableFont(),
-        mDefaultSerifFont(StyleGenericFontFamily::Serif, 0),
-        mDefaultSansSerifFont(StyleGenericFontFamily::SansSerif, 0),
-        mDefaultMonospaceFont(StyleGenericFontFamily::Monospace, 0),
-        mDefaultCursiveFont(StyleGenericFontFamily::Cursive, 0),
-        mDefaultFantasyFont(StyleGenericFontFamily::Fantasy, 0) {
-    mDefaultVariableFont.fontlist.SetDefaultFontType(
-        StyleGenericFontFamily::Serif);
+        mDefaultFixedFont(mozilla::eFamily_monospace, 0),
+        mDefaultSerifFont(mozilla::eFamily_serif, 0),
+        mDefaultSansSerifFont(mozilla::eFamily_sans_serif, 0),
+        mDefaultMonospaceFont(mozilla::eFamily_monospace, 0),
+        mDefaultCursiveFont(mozilla::eFamily_cursive, 0),
+        mDefaultFantasyFont(mozilla::eFamily_fantasy, 0) {
+    mDefaultVariableFont.fontlist.SetDefaultFontType(mozilla::eFamily_serif);
     // 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;
@@ -62,47 +62,58 @@ struct LangGroupFontPrefs {
   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
+   * kGenericFont_moz_fixed, 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) {
+  const nsFont* GetDefaultFont(uint8_t aFontID) const {
+    switch (aFontID) {
       // Special (our default variable width font and fixed width font)
-      case StyleGenericFontFamily::None:
+      case kGenericFont_moz_variable:
         return &mDefaultVariableFont;
+      case kGenericFont_moz_fixed:
+        return &mDefaultFixedFont;
       // CSS
-      case StyleGenericFontFamily::Serif:
+      case kGenericFont_serif:
         return &mDefaultSerifFont;
-      case StyleGenericFontFamily::SansSerif:
+      case kGenericFont_sans_serif:
         return &mDefaultSansSerifFont;
-      case StyleGenericFontFamily::Monospace:
+      case kGenericFont_monospace:
         return &mDefaultMonospaceFont;
-      case StyleGenericFontFamily::Cursive:
+      case kGenericFont_cursive:
         return &mDefaultCursiveFont;
-      case StyleGenericFontFamily::Fantasy:
+      case kGenericFont_fantasy:
         return &mDefaultFantasyFont;
         break;
       default:
         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;
 };
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -9744,19 +9744,18 @@ already_AddRefed<nsFontMetrics> nsLayout
 void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
                                       LookAndFeel::FontID aFontID,
                                       const nsFont* aDefaultVariableFont) {
   gfxFontStyle fontStyle;
   nsAutoString systemFontName;
   if (LookAndFeel::GetFont(aFontID, systemFontName, fontStyle)) {
     systemFontName.Trim("\"'");
     aSystemFont->fontlist =
-        FontFamilyList(NS_ConvertUTF16toUTF8(systemFontName),
-                       StyleFontFamilyNameSyntax::Identifiers);
-    aSystemFont->fontlist.SetDefaultFontType(StyleGenericFontFamily::None);
+        FontFamilyList(NS_ConvertUTF16toUTF8(systemFontName), eUnquotedName);
+    aSystemFont->fontlist.SetDefaultFontType(eFamily_none);
     aSystemFont->style = fontStyle.style;
     aSystemFont->systemFont = fontStyle.systemFont;
     aSystemFont->weight = fontStyle.weight;
     aSystemFont->stretch = fontStyle.stretch;
     aSystemFont->size = CSSPixel::ToAppUnits(fontStyle.size);
     // aSystemFont->langGroup = fontStyle.langGroup;
     aSystemFont->sizeAdjust = fontStyle.sizeAdjust;
 
--- a/layout/generic/nsSimplePageSequenceFrame.cpp
+++ b/layout/generic/nsSimplePageSequenceFrame.cpp
@@ -48,22 +48,23 @@ nsSimplePageSequenceFrame::nsSimplePageS
     ComputedStyle* aStyle, nsPresContext* aPresContext)
     : nsContainerFrame(aStyle, aPresContext, kClassID),
       mTotalPages(-1),
       mCalledBeginPage(false),
       mCurrentCanvasListSetup(false) {
   nscoord halfInch = PresContext()->CSSTwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5));
   mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch);
 
+  // XXX Unsafe to assume successful allocation
   mPageData = new nsSharedPageData();
   mPageData->mHeadFootFont =
       *PresContext()
            ->Document()
            ->GetFontPrefsForLang(aStyle->StyleFont()->mLanguage)
-           ->GetDefaultFont(StyleGenericFontFamily::Serif);
+           ->GetDefaultFont(kGenericFont_serif);
   mPageData->mHeadFootFont.size = nsPresContext::CSSPointsToAppUnits(10);
 
   // Doing this here so we only have to go get these formats once
   SetPageNumberFormat("pagenumber", "%1$d", true);
   SetPageNumberFormat("pageofpages", "%1$d of %2$d", false);
 }
 
 nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() {
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5726,17 +5726,17 @@ gfxFloat nsTextFrame::ComputeSelectionUn
       // metrics.  It should be constant pixels value which is decided from the
       // default font size.  Note that if the actual font size is smaller than
       // the default font size, we should use the actual font size because the
       // computed value from the default font size can be too thick for the
       // current font size.
       nscoord defaultFontSize =
           aPresContext->Document()
               ->GetFontPrefsForLang(nullptr)
-              ->GetDefaultFont(StyleGenericFontFamily::None)
+              ->GetDefaultFont(kPresContext_DefaultVariableFont_ID)
               ->size;
       int32_t zoomedFontSize = aPresContext->AppUnitsToDevPixels(
           nsStyleFont::ZoomText(*aPresContext->Document(), defaultFontSize));
       gfxFloat fontSize =
           std::min(gfxFloat(zoomedFontSize), aFontMetrics.emHeight);
       fontSize = std::max(fontSize, 1.0);
       return ceil(fontSize / 20);
     }
--- a/layout/inspector/InspectorFontFace.cpp
+++ b/layout/inspector/InspectorFontFace.cpp
@@ -26,43 +26,45 @@ InspectorFontFace::InspectorFontFace(gfx
                                      FontMatchType aMatchType)
     : mFontEntry(aFontEntry), mFontGroup(aFontGroup), mMatchType(aMatchType) {
   MOZ_COUNT_CTOR(InspectorFontFace);
 }
 
 InspectorFontFace::~InspectorFontFace() { MOZ_COUNT_DTOR(InspectorFontFace); }
 
 bool InspectorFontFace::FromFontGroup() {
-  return bool(mMatchType.kind & FontMatchType::Kind::kFontGroup);
+  return bool(mMatchType & FontMatchType::kFontGroup);
 }
 
 bool InspectorFontFace::FromLanguagePrefs() {
-  return bool(mMatchType.kind & FontMatchType::Kind::kPrefsFallback);
+  return bool(mMatchType & FontMatchType::kPrefsFallback);
 }
 
 bool InspectorFontFace::FromSystemFallback() {
-  return bool(mMatchType.kind & FontMatchType::Kind::kSystemFallback);
+  return bool(mMatchType & FontMatchType::kSystemFallback);
 }
 
 void InspectorFontFace::GetName(nsAString& aName) {
   if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
     NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
     aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->mUserFontData->mRealName));
   } else {
     aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->RealFaceName()));
   }
 }
 
 void InspectorFontFace::GetCSSFamilyName(nsAString& aCSSFamilyName) {
   aCSSFamilyName.Append(NS_ConvertUTF8toUTF16(mFontEntry->FamilyName()));
 }
 
 void InspectorFontFace::GetCSSGeneric(nsAString& aName) {
-  if (mMatchType.generic != StyleGenericFontFamily::None) {
-    aName.AssignASCII(gfxPlatformFontList::GetGenericName(mMatchType.generic));
+  auto genericType = FontFamilyType(mMatchType & FontMatchType::kGenericMask);
+  if (genericType >= FontFamilyType::eFamily_generic_first &&
+      genericType <= FontFamilyType::eFamily_generic_last) {
+    aName.AssignASCII(gfxPlatformFontList::GetGenericName(genericType));
   } else {
     aName.Truncate(0);
   }
 }
 
 CSSFontFaceRule* InspectorFontFace::GetRule() {
   if (!mRule) {
     // check whether this font entry is associated with an @font-face rule
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -51,23 +51,23 @@ using namespace mozilla::image;
 // BUG 848725 Drawing failure with stretchy horizontal parenthesis when no fonts
 // are installed. "kMaxScaleFactor" is required to limit the scale for the
 // vertical and horizontal stretchy operators.
 static const float kMaxScaleFactor = 20.0;
 static const float kLargeOpFactor = float(M_SQRT2);
 static const float kIntegralFactor = 2.0;
 
 static void NormalizeDefaultFont(nsFont& aFont, float aFontSizeInflation) {
-  if (aFont.fontlist.GetDefaultFontType() != StyleGenericFontFamily::None) {
+  if (aFont.fontlist.GetDefaultFontType() != eFamily_none) {
     nsTArray<FontFamilyName> names;
     names.AppendElements(aFont.fontlist.GetFontlist()->mNames);
     names.AppendElement(FontFamilyName(aFont.fontlist.GetDefaultFontType()));
 
     aFont.fontlist.SetFontlist(std::move(names));
-    aFont.fontlist.SetDefaultFontType(StyleGenericFontFamily::None);
+    aFont.fontlist.SetDefaultFontType(eFamily_none);
   }
   aFont.size = NSToCoordRound(aFont.size * aFontSizeInflation);
 }
 
 // -----------------------------------------------------------------------------
 static const nsGlyphCode kNullGlyph = {{{0, 0}}, 0};
 
 // -----------------------------------------------------------------------------
@@ -161,18 +161,18 @@ static nsresult LoadProperties(const nsA
                                                 uriStr);
 }
 
 class nsPropertiesTable final : public nsGlyphTable {
  public:
   explicit nsPropertiesTable(const nsACString& aPrimaryFontName)
       : mState(NS_TABLE_STATE_EMPTY) {
     MOZ_COUNT_CTOR(nsPropertiesTable);
-    mGlyphCodeFonts.AppendElement(FontFamilyName(
-        aPrimaryFontName, StyleFontFamilyNameSyntax::Identifiers));
+    mGlyphCodeFonts.AppendElement(
+        FontFamilyName(aPrimaryFontName, eUnquotedName));
   }
 
   ~nsPropertiesTable() { MOZ_COUNT_DTOR(nsPropertiesTable); }
 
   const FontFamilyName& PrimaryFontName() const { return mGlyphCodeFonts[0]; }
 
   const FontFamilyName& FontNameFor(
       const nsGlyphCode& aGlyphCode) const override {
@@ -281,18 +281,17 @@ nsGlyphCode nsPropertiesTable::ElementAt
     for (int32_t i = 1;; i++) {
       key.AssignLiteral("external.");
       key.AppendInt(i, 10);
       rv = mGlyphProperties->GetStringProperty(key, value);
       if (NS_FAILED(rv)) break;
       Clean(value);
       mGlyphCodeFonts.AppendElement(FontFamilyName(
           NS_ConvertUTF16toUTF8(value),
-          StyleFontFamilyNameSyntax::Identifiers));  // i.e., mGlyphCodeFonts[i]
-                                                     // holds this font name
+          eUnquotedName));  // i.e., mGlyphCodeFonts[i] holds this font name
     }
   }
 
   // Update our cache if it is not associated to this character
   if (mCharCache != aChar) {
     // The key in the property file is interpreted as ASCII and kept
     // as such ...
     char key[10];
@@ -415,18 +414,17 @@ class nsOpenTypeTable final : public nsG
 
  private:
   RefPtr<gfxFont> mFont;
   FontFamilyName mFontFamilyName;
   uint32_t mGlyphID;
 
   explicit nsOpenTypeTable(gfxFont* aFont)
       : mFont(aFont),
-        mFontFamilyName(aFont->GetFontEntry()->FamilyName(),
-                        StyleFontFamilyNameSyntax::Identifiers),
+        mFontFamilyName(aFont->GetFontEntry()->FamilyName(), eUnquotedName),
         mGlyphID(0) {
     MOZ_COUNT_CTOR(nsOpenTypeTable);
   }
 
   void UpdateCache(DrawTarget* aDrawTarget, int32_t aAppUnitsPerDevPixel,
                    gfxFontGroup* aFontGroup, char16_t aChar);
 };
 
@@ -513,17 +511,17 @@ already_AddRefed<gfxTextRun> nsOpenTypeT
                "nsOpenTypeTable can only access glyphs by id");
 
   gfxTextRunFactory::Parameters params = {
       aDrawTarget, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel};
   RefPtr<gfxTextRun> textRun =
       gfxTextRun::Create(&params, 1, aFontGroup, gfx::ShapedTextFlags(),
                          nsTextFrameUtils::Flags());
   textRun->AddGlyphRun(aFontGroup->GetFirstValidFont(),
-                       FontMatchType::Kind::kFontGroup, 0, false,
+                       FontMatchType::kFontGroup, 0, false,
                        gfx::ShapedTextFlags::TEXT_ORIENT_HORIZONTAL);
   // We don't care about CSS writing mode here;
   // math runs are assumed to be horizontal.
   gfxTextRun::DetailedGlyph detailedGlyph;
   detailedGlyph.mGlyphID = aGlyph.glyphID;
   detailedGlyph.mAdvance = NSToCoordRound(
       aAppUnitsPerDevPixel * aFontGroup->GetFirstValidFont()->GetGlyphHAdvance(
                                  aDrawTarget, aGlyph.glyphID));
@@ -887,17 +885,17 @@ bool nsMathMLChar::SetFontFamily(nsPresC
     params.textPerf = aPresContext->GetTextPerfMetrics();
     params.featureValueLookup = aPresContext->GetFontFeatureValuesLookup();
     RefPtr<nsFontMetrics> fm =
         aPresContext->DeviceContext()->GetMetricsFor(font, params);
     // Set the font if it is an unicode table
     // or if the same family name has been found
     gfxFont* firstFont = fm->GetThebesFontGroup()->GetFirstValidFont();
     FontFamilyList firstFontList(firstFont->GetFontEntry()->FamilyName(),
-                                 StyleFontFamilyNameSyntax::Identifiers);
+                                 eUnquotedName);
     if (aGlyphTable == &gGlyphTableList->mUnicodeTable ||
         firstFontList == familyList) {
       aFont.fontlist = familyList;
       *aFontGroup = fm->GetThebesFontGroup();
     } else {
       return false;  // We did not set the font
     }
   }
@@ -1277,27 +1275,27 @@ bool nsMathMLChar::StretchEnumContext::T
 
 // This is called for each family, whether it exists or not
 bool nsMathMLChar::StretchEnumContext::EnumCallback(
     const FontFamilyName& aFamily, bool aGeneric, void* aData) {
   StretchEnumContext* context = static_cast<StretchEnumContext*>(aData);
 
   // for comparisons, force use of unquoted names
   FontFamilyName unquotedFamilyName(aFamily);
-  if (unquotedFamilyName.mSyntax == StyleFontFamilyNameSyntax::Quoted) {
-    unquotedFamilyName.mSyntax = StyleFontFamilyNameSyntax::Identifiers;
+  if (unquotedFamilyName.mType == eFamily_named_quoted) {
+    unquotedFamilyName.mType = eFamily_named;
   }
 
   // Check font family if it is not a generic one
   // We test with the kNullGlyph
   ComputedStyle* sc = context->mChar->mComputedStyle;
   nsFont font = sc->StyleFont()->mFont;
   NormalizeDefaultFont(font, context->mFontSizeInflation);
   RefPtr<gfxFontGroup> fontGroup;
-  FontFamilyList family({unquotedFamilyName});
+  FontFamilyList family(unquotedFamilyName);
   if (!aGeneric &&
       !context->mChar->SetFontFamily(context->mPresContext, nullptr, kNullGlyph,
                                      family, font, &fontGroup))
     return true;  // Could not set the family
 
   // Determine the glyph table to use for this font.
   nsAutoPtr<nsOpenTypeTable> openTypeTable;
   nsGlyphTable* glyphTable;
@@ -1340,18 +1338,17 @@ bool nsMathMLChar::StretchEnumContext::E
     return false;  // no need to continue
 
   return true;  // true means continue
 }
 
 static void AppendFallbacks(nsTArray<FontFamilyName>& aNames,
                             const nsTArray<nsCString>& aFallbacks) {
   for (const nsCString& fallback : aFallbacks) {
-    aNames.AppendElement(
-        FontFamilyName(fallback, StyleFontFamilyNameSyntax::Identifiers));
+    aNames.AppendElement(FontFamilyName(fallback, eUnquotedName));
   }
 }
 
 // insert math fallback families just before the first generic or at the end
 // when no generic present
 static void InsertMathFallbacks(FontFamilyList& aFamilyList,
                                 nsTArray<nsCString>& aFallbacks) {
   nsTArray<FontFamilyName> mergedList;
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -86,19 +86,19 @@ using namespace mozilla::css;
 using namespace mozilla::dom;
 
 // Definitions of the global traversal stats.
 bool ServoTraversalStatistics::sActive = false;
 ServoTraversalStatistics ServoTraversalStatistics::sSingleton;
 
 static RWLock* sServoFFILock = nullptr;
 
-static const nsFont* ThreadSafeGetDefaultFontHelper(
-    const Document& aDocument, nsAtom* aLanguage,
-    StyleGenericFontFamily aGenericId) {
+static const nsFont* ThreadSafeGetDefaultFontHelper(const Document& aDocument,
+                                                    nsAtom* aLanguage,
+                                                    uint8_t aGenericId) {
   bool needsCache = false;
   const nsFont* retval;
 
   auto GetDefaultFont = [&](bool* aNeedsToCache) {
     auto* prefs = aDocument.GetFontPrefsForLang(aLanguage, aNeedsToCache);
     return prefs ? prefs->GetDefaultFont(aGenericId) : nullptr;
   };
 
@@ -957,24 +957,24 @@ nsAtom* Gecko_Atomize(const char* aStrin
 nsAtom* Gecko_Atomize16(const nsAString* aString) {
   return NS_Atomize(*aString).take();
 }
 
 void Gecko_AddRefAtom(nsAtom* aAtom) { NS_ADDREF(aAtom); }
 
 void Gecko_ReleaseAtom(nsAtom* aAtom) { NS_RELEASE(aAtom); }
 
-void Gecko_nsTArray_FontFamilyName_AppendNamed(
-    nsTArray<FontFamilyName>* aNames, nsAtom* aName,
-    StyleFontFamilyNameSyntax aSyntax) {
-  aNames->AppendElement(FontFamilyName(aName, aSyntax));
+void Gecko_nsTArray_FontFamilyName_AppendNamed(nsTArray<FontFamilyName>* aNames,
+                                               nsAtom* aName, bool aQuoted) {
+  aNames->AppendElement(
+      FontFamilyName(aName, aQuoted ? eQuotedName : eUnquotedName));
 }
 
 void Gecko_nsTArray_FontFamilyName_AppendGeneric(
-    nsTArray<FontFamilyName>* aNames, StyleGenericFontFamily aType) {
+    nsTArray<FontFamilyName>* aNames, FontFamilyType aType) {
   aNames->AppendElement(FontFamilyName(aType));
 }
 
 SharedFontList* Gecko_SharedFontList_Create() {
   RefPtr<SharedFontList> fontlist = new SharedFontList();
   return fontlist.forget().take();
 }
 
@@ -997,35 +997,35 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(Share
 void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src) {
   dst->fontlist = src->fontlist;
 }
 
 void Gecko_nsFont_InitSystem(nsFont* aDest, int32_t aFontId,
                              const nsStyleFont* aFont,
                              const Document* aDocument) {
   const nsFont* defaultVariableFont = ThreadSafeGetDefaultFontHelper(
-      *aDocument, aFont->mLanguage, StyleGenericFontFamily::None);
+      *aDocument, aFont->mLanguage, kPresContext_DefaultVariableFont_ID);
 
   // We have passed uninitialized memory to this function,
   // initialize it. We can't simply return an nsFont because then
   // we need to know its size beforehand. Servo cannot initialize nsFont
   // itself, so this will do.
   new (aDest) nsFont(*defaultVariableFont);
 
   LookAndFeel::FontID fontID = static_cast<LookAndFeel::FontID>(aFontId);
 
   AutoWriteLock guard(*sServoFFILock);
   nsLayoutUtils::ComputeSystemFont(aDest, fontID, defaultVariableFont);
 }
 
 void Gecko_nsFont_Destroy(nsFont* aDest) { aDest->~nsFont(); }
 
-StyleGenericFontFamily Gecko_nsStyleFont_ComputeDefaultFontType(
-    const Document* aDoc, StyleGenericFontFamily aGenericId,
-    nsAtom* aLanguage) {
+FontFamilyType Gecko_nsStyleFont_ComputeDefaultFontType(const Document* aDoc,
+                                                        uint8_t aGenericId,
+                                                        nsAtom* aLanguage) {
   const nsFont* defaultFont =
       ThreadSafeGetDefaultFontHelper(*aDoc, aLanguage, aGenericId);
   return defaultFont->fontlist.GetDefaultFontType();
 }
 
 gfxFontFeatureValueSet* Gecko_ConstructFontFeatureValueSet() {
   return new gfxFontFeatureValueSet();
 }
@@ -1887,25 +1887,42 @@ void Gecko_nsStyleFont_SetLang(nsStyleFo
   aFont->mExplicitLanguage = true;
 }
 
 void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont,
                                     const nsStyleFont* aSource) {
   aFont->mLanguage = aSource->mLanguage;
 }
 
-void Gecko_nsStyleFont_PrioritizeUserFonts(
-    nsStyleFont* aFont, StyleGenericFontFamily aDefaultGeneric) {
+void Gecko_nsStyleFont_PrioritizeUserFonts(nsStyleFont* aFont,
+                                           FontFamilyType aDefaultGeneric) {
   MOZ_ASSERT(!StaticPrefs::browser_display_use_document_fonts());
-  MOZ_ASSERT(aDefaultGeneric != StyleGenericFontFamily::None);
+  MOZ_ASSERT(aDefaultGeneric != eFamily_none);
   if (!aFont->mFont.fontlist.PrioritizeFirstGeneric()) {
     aFont->mFont.fontlist.PrependGeneric(aDefaultGeneric);
   }
 }
 
+void Gecko_nsStyleFont_PrefillDefaultForGeneric(nsStyleFont* aFont,
+                                                const Document* aDocument,
+                                                uint8_t aGenericId) {
+  const nsFont* defaultFont =
+      ThreadSafeGetDefaultFontHelper(*aDocument, aFont->mLanguage, aGenericId);
+  // In case of just the language changing, the parent could have had no
+  // generic, which Gecko just does regular cascading with. Do the same. This
+  // can only happen in the case where the language changed but the family did
+  // not
+  if (aGenericId != kGenericFont_NONE) {
+    aFont->mFont.fontlist = defaultFont->fontlist;
+  } else {
+    aFont->mFont.fontlist.SetDefaultFontType(
+        defaultFont->fontlist.GetDefaultFontType());
+  }
+}
+
 nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont* aFont,
                                          const Document* aDocument) {
   // Don't change font-size:0, since that would un-hide hidden text, nor chrome
   // docs, we assume those know what they do.
   if (aFont->mSize == 0 || nsContentUtils::IsChromeDoc(aDocument)) {
     return 0;
   }
 
@@ -1932,16 +1949,17 @@ nscoord Gecko_nsStyleFont_ComputeMinSize
     return 0;
   }
 
   return (minFontSize * aFont->mMinFontSizeRatio) / 100;
 }
 
 void FontSizePrefs::CopyFrom(const LangGroupFontPrefs& prefs) {
   mDefaultVariableSize = prefs.mDefaultVariableFont.size;
+  mDefaultFixedSize = prefs.mDefaultFixedFont.size;
   mDefaultSerifSize = prefs.mDefaultSerifFont.size;
   mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size;
   mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size;
   mDefaultCursiveSize = prefs.mDefaultCursiveFont.size;
   mDefaultFantasySize = prefs.mDefaultFantasyFont.size;
 }
 
 FontSizePrefs Gecko_GetBaseSize(nsAtom* aLanguage) {
--- a/layout/style/GeckoBindings.h
+++ b/layout/style/GeckoBindings.h
@@ -261,21 +261,20 @@ nsAtom* Gecko_Atomize(const char* aStrin
 nsAtom* Gecko_Atomize16(const nsAString* aString);
 void Gecko_AddRefAtom(nsAtom* aAtom);
 void Gecko_ReleaseAtom(nsAtom* aAtom);
 
 // Font style
 void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src);
 
 void Gecko_nsTArray_FontFamilyName_AppendNamed(
-    nsTArray<mozilla::FontFamilyName>* aNames, nsAtom* aName,
-    mozilla::StyleFontFamilyNameSyntax);
+    nsTArray<mozilla::FontFamilyName>* aNames, nsAtom* aName, bool aQuoted);
 
 void Gecko_nsTArray_FontFamilyName_AppendGeneric(
-    nsTArray<mozilla::FontFamilyName>* aNames, mozilla::StyleGenericFontFamily);
+    nsTArray<mozilla::FontFamilyName>* aNames, mozilla::FontFamilyType aType);
 
 // Returns an already-AddRefed SharedFontList with an empty mNames array.
 mozilla::SharedFontList* Gecko_SharedFontList_Create();
 
 size_t Gecko_SharedFontList_SizeOfIncludingThis(
     mozilla::SharedFontList* fontlist);
 
 size_t Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(
@@ -674,25 +673,28 @@ void Gecko_nsStyleFont_CopyLangFrom(nsSt
                                     const nsStyleFont* aSource);
 
 // Moves the generic family in the font-family to the front, or prepends
 // aDefaultGeneric, so that user-configured fonts take precedent over document
 // fonts.
 //
 // Document fonts may still be used as fallback for unsupported glyphs though.
 void Gecko_nsStyleFont_PrioritizeUserFonts(
-    nsStyleFont* font, mozilla::StyleGenericFontFamily aDefaultGeneric);
+    nsStyleFont* font, mozilla::FontFamilyType aDefaultGeneric);
+
+void Gecko_nsStyleFont_PrefillDefaultForGeneric(nsStyleFont* font,
+                                                const mozilla::dom::Document*,
+                                                uint8_t generic_id);
 
 nscoord Gecko_nsStyleFont_ComputeMinSize(const nsStyleFont*,
                                          const mozilla::dom::Document*);
 
 // Computes the default generic font for a generic family and language.
-mozilla::StyleGenericFontFamily Gecko_nsStyleFont_ComputeDefaultFontType(
-    const mozilla::dom::Document*,
-    mozilla::StyleGenericFontFamily generic_family, nsAtom* language);
+mozilla::FontFamilyType Gecko_nsStyleFont_ComputeDefaultFontType(
+    const mozilla::dom::Document*, uint8_t generic_family, nsAtom* language);
 
 mozilla::FontSizePrefs Gecko_GetBaseSize(nsAtom* lang);
 
 // XBL related functions.
 const mozilla::dom::Element* Gecko_GetBindingParent(
     const mozilla::dom::Element*);
 
 const RawServoAuthorStyles* Gecko_XBLBinding_GetRawServoStyles(
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -59,16 +59,17 @@ bitfield-enums = [
 rusty-enums = [
     "nsCompatibility",
     "mozilla::EffectCompositor_CascadeLevel",
     "mozilla::SheetType",
     "mozilla::dom::CallerType",
     "mozilla::dom::IterationCompositeOperation",
     "mozilla::dom::CompositeOperation",
     "mozilla::InheritTarget",
+    "mozilla::FontFamilyType",
     "mozilla::css::DocumentMatchingFunction",
     "mozilla::css::SheetParsingMode",
     "mozilla::StyleContentType",
     "nsStyleSVGOpacitySource",
     "nsStyleUnit",
     "nsCSSKeyword",
     "mozilla::dom::Document_DocumentTheme",
     "mozilla::dom::Document_Type",
@@ -452,18 +453,16 @@ cbindgen-types = [
     { gecko = "StyleRestyleHint", servo = "invalidation::element::restyle_hints::RestyleHint" },
     { gecko = "StyleTouchAction", servo = "values::computed::TouchAction" },
     { gecko = "StyleWillChangeBits", servo = "values::specified::box_::WillChangeBits" },
     { gecko = "StyleTextDecorationLine", servo = "values::computed::TextDecorationLine" },
     { gecko = "StyleMozListReversed", servo = "values::computed::MozListReversed" },
     { gecko = "StyleOwned", servo = "gecko_bindings::sugar::ownership::Owned" },
     { gecko = "StyleOwnedOrNull", servo = "gecko_bindings::sugar::ownership::OwnedOrNull" },
     { gecko = "StyleStrong", servo = "gecko_bindings::sugar::ownership::Strong" },
-    { gecko = "StyleGenericFontFamily", servo = "values::computed::font::GenericFontFamily" },
-    { gecko = "StyleFontFamilyNameSyntax", servo = "values::computed::font::FontFamilyNameSyntax" },
 ]
 
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::RustCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -156,16 +156,17 @@ struct MediumFeaturesChangedResult {
   bool mAffectsDocumentRules;
   bool mAffectsNonDocumentRules;
   bool mUsesViewportUnits;
 };
 
 struct FontSizePrefs {
   void CopyFrom(const mozilla::LangGroupFontPrefs&);
   nscoord mDefaultVariableSize;
+  nscoord mDefaultFixedSize;
   nscoord mDefaultSerifSize;
   nscoord mDefaultSansSerifSize;
   nscoord mDefaultMonospaceSize;
   nscoord mDefaultCursiveSize;
   nscoord mDefaultFantasySize;
 };
 
 }  // namespace mozilla
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -107,22 +107,22 @@ nsStyleFont::nsStyleFont(const nsStyleFo
       mScriptMinSize(aSrc.mScriptMinSize),
       mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier),
       mLanguage(aSrc.mLanguage) {
   MOZ_COUNT_CTOR(nsStyleFont);
 }
 
 nsStyleFont::nsStyleFont(const Document& aDocument)
     : mFont(*aDocument.GetFontPrefsForLang(nullptr)->GetDefaultFont(
-          StyleGenericFontFamily::None)),
+          kPresContext_DefaultVariableFont_ID)),
       mSize(ZoomText(aDocument, mFont.size)),
       mFontSizeFactor(1.0),
       mFontSizeOffset(0),
       mFontSizeKeyword(NS_STYLE_FONT_SIZE_MEDIUM),
-      mGenericID(StyleGenericFontFamily::None),
+      mGenericID(kGenericFont_NONE),
       mScriptLevel(0),
       mMathVariant(NS_MATHML_MATHVARIANT_NONE),
       mMathDisplay(NS_MATHML_DISPLAYSTYLE_INLINE),
       mMinFontSizeRatio(100),  // 100%
       mExplicitLanguage(false),
       mAllowZoom(true),
       mScriptUnconstrainedSize(mSize),
       mScriptMinSize(nsPresContext::CSSTwipsToAppUnits(
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -100,17 +100,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   // In stylo these three track whether the size is keyword-derived
   // and if so if it has been modified by a factor/offset
   float mFontSizeFactor;
   nscoord mFontSizeOffset;
   uint8_t mFontSizeKeyword;  // NS_STYLE_FONT_SIZE_*, is
                              // NS_STYLE_FONT_SIZE_NO_KEYWORD when not
                              // keyword-derived
 
-  mozilla::StyleGenericFontFamily mGenericID;
+  uint8_t mGenericID;  // generic CSS font family, if any;
+                       // value is a kGenericFont_* constant, see nsFont.h.
 
   // MathML scriptlevel support
   int8_t mScriptLevel;
   // MathML  mathvariant support
   uint8_t mMathVariant;
   // MathML displaystyle support
   uint8_t mMathDisplay;
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3437,159 +3437,159 @@ pref("svg.transform-box.enabled", true);
 # Also, these keywords are currently not part of any spec, which is partly why
 # we disable them for web content.
 pref("svg.context-properties.content.enabled", false);
 
 // Default font types and sizes by locale
 pref("font.default.ar", "sans-serif");
 pref("font.minimum-size.ar", 0);
 pref("font.size.variable.ar", 16);
-pref("font.size.monospace.ar", 13);
+pref("font.size.fixed.ar", 13);
 
 pref("font.default.el", "serif");
 pref("font.minimum-size.el", 0);
 pref("font.size.variable.el", 16);
-pref("font.size.monospace.el", 13);
+pref("font.size.fixed.el", 13);
 
 pref("font.default.he", "sans-serif");
 pref("font.minimum-size.he", 0);
 pref("font.size.variable.he", 16);
-pref("font.size.monospace.he", 13);
+pref("font.size.fixed.he", 13);
 
 pref("font.default.ja", "sans-serif");
 pref("font.minimum-size.ja", 0);
 pref("font.size.variable.ja", 16);
-pref("font.size.monospace.ja", 16);
+pref("font.size.fixed.ja", 16);
 
 pref("font.default.ko", "sans-serif");
 pref("font.minimum-size.ko", 0);
 pref("font.size.variable.ko", 16);
-pref("font.size.monospace.ko", 16);
+pref("font.size.fixed.ko", 16);
 
 pref("font.default.th", "sans-serif");
 pref("font.minimum-size.th", 0);
 pref("font.size.variable.th", 16);
-pref("font.size.monospace.th", 13);
+pref("font.size.fixed.th", 13);
 
 pref("font.default.x-cyrillic", "serif");
 pref("font.minimum-size.x-cyrillic", 0);
 pref("font.size.variable.x-cyrillic", 16);
-pref("font.size.monospace.x-cyrillic", 13);
+pref("font.size.fixed.x-cyrillic", 13);
 
 pref("font.default.x-devanagari", "serif");
 pref("font.minimum-size.x-devanagari", 0);
 pref("font.size.variable.x-devanagari", 16);
-pref("font.size.monospace.x-devanagari", 13);
+pref("font.size.fixed.x-devanagari", 13);
 
 pref("font.default.x-tamil", "serif");
 pref("font.minimum-size.x-tamil", 0);
 pref("font.size.variable.x-tamil", 16);
-pref("font.size.monospace.x-tamil", 13);
+pref("font.size.fixed.x-tamil", 13);
 
 pref("font.default.x-armn", "serif");
 pref("font.minimum-size.x-armn", 0);
 pref("font.size.variable.x-armn", 16);
-pref("font.size.monospace.x-armn", 13);
+pref("font.size.fixed.x-armn", 13);
 
 pref("font.default.x-beng", "serif");
 pref("font.minimum-size.x-beng", 0);
 pref("font.size.variable.x-beng", 16);
-pref("font.size.monospace.x-beng", 13);
+pref("font.size.fixed.x-beng", 13);
 
 pref("font.default.x-cans", "serif");
 pref("font.minimum-size.x-cans", 0);
 pref("font.size.variable.x-cans", 16);
-pref("font.size.monospace.x-cans", 13);
+pref("font.size.fixed.x-cans", 13);
 
 pref("font.default.x-ethi", "serif");
 pref("font.minimum-size.x-ethi", 0);
 pref("font.size.variable.x-ethi", 16);
-pref("font.size.monospace.x-ethi", 13);
+pref("font.size.fixed.x-ethi", 13);
 
 pref("font.default.x-geor", "serif");
 pref("font.minimum-size.x-geor", 0);
 pref("font.size.variable.x-geor", 16);
-pref("font.size.monospace.x-geor", 13);
+pref("font.size.fixed.x-geor", 13);
 
 pref("font.default.x-gujr", "serif");
 pref("font.minimum-size.x-gujr", 0);
 pref("font.size.variable.x-gujr", 16);
-pref("font.size.monospace.x-gujr", 13);
+pref("font.size.fixed.x-gujr", 13);
 
 pref("font.default.x-guru", "serif");
 pref("font.minimum-size.x-guru", 0);
 pref("font.size.variable.x-guru", 16);
-pref("font.size.monospace.x-guru", 13);
+pref("font.size.fixed.x-guru", 13);
 
 pref("font.default.x-khmr", "serif");
 pref("font.minimum-size.x-khmr", 0);
 pref("font.size.variable.x-khmr", 16);
-pref("font.size.monospace.x-khmr", 13);
+pref("font.size.fixed.x-khmr", 13);
 
 pref("font.default.x-mlym", "serif");
 pref("font.minimum-size.x-mlym", 0);
 pref("font.size.variable.x-mlym", 16);
-pref("font.size.monospace.x-mlym", 13);
+pref("font.size.fixed.x-mlym", 13);
 
 pref("font.default.x-orya", "serif");
 pref("font.minimum-size.x-orya", 0);
 pref("font.size.variable.x-orya", 16);
-pref("font.size.monospace.x-orya", 13);
+pref("font.size.fixed.x-orya", 13);
 
 pref("font.default.x-telu", "serif");
 pref("font.minimum-size.x-telu", 0);
 pref("font.size.variable.x-telu", 16);
-pref("font.size.monospace.x-telu", 13);
+pref("font.size.fixed.x-telu", 13);
 
 pref("font.default.x-knda", "serif");
 pref("font.minimum-size.x-knda", 0);
 pref("font.size.variable.x-knda", 16);
-pref("font.size.monospace.x-knda", 13);
+pref("font.size.fixed.x-knda", 13);
 
 pref("font.default.x-sinh", "serif");
 pref("font.minimum-size.x-sinh", 0);
 pref("font.size.variable.x-sinh", 16);
-pref("font.size.monospace.x-sinh", 13);
+pref("font.size.fixed.x-sinh", 13);
 
 pref("font.default.x-tibt", "serif");
 pref("font.minimum-size.x-tibt", 0);
 pref("font.size.variable.x-tibt", 16);
-pref("font.size.monospace.x-tibt", 13);
+pref("font.size.fixed.x-tibt", 13);
 
 pref("font.default.x-unicode", "serif");
 pref("font.minimum-size.x-unicode", 0);
 pref("font.size.variable.x-unicode", 16);
-pref("font.size.monospace.x-unicode", 13);
+pref("font.size.fixed.x-unicode", 13);
 
 pref("font.default.x-western", "serif");
 pref("font.minimum-size.x-western", 0);
 pref("font.size.variable.x-western", 16);
-pref("font.size.monospace.x-western", 13);
+pref("font.size.fixed.x-western", 13);
 
 pref("font.default.zh-CN", "sans-serif");
 pref("font.minimum-size.zh-CN", 0);
 pref("font.size.variable.zh-CN", 16);
-pref("font.size.monospace.zh-CN", 16);
+pref("font.size.fixed.zh-CN", 16);
 
 pref("font.default.zh-HK", "sans-serif");
 pref("font.minimum-size.zh-HK", 0);
 pref("font.size.variable.zh-HK", 16);
-pref("font.size.monospace.zh-HK", 16);
+pref("font.size.fixed.zh-HK", 16);
 
 pref("font.default.zh-TW", "sans-serif");
 pref("font.minimum-size.zh-TW", 0);
 pref("font.size.variable.zh-TW", 16);
-pref("font.size.monospace.zh-TW", 16);
+pref("font.size.fixed.zh-TW", 16);
 
 // mathml.css sets font-size to "inherit" and font-family to "serif" so only
 // font.name.*.x-math and font.minimum-size.x-math are really relevant.
 pref("font.default.x-math", "serif");
 pref("font.minimum-size.x-math", 0);
 pref("font.size.variable.x-math", 16);
-pref("font.size.monospace.x-math", 13);
+pref("font.size.fixed.x-math", 13);
 
 /*
  * A value greater than zero enables font size inflation for
  * pan-and-zoom UIs, so that the fonts in a block are at least the size
  * that, if a block's width is scaled to match the device's width, the
  * fonts in the block are big enough that at most the pref value ems of
  * text fit in *the width of the device*.
  *
@@ -4417,29 +4417,29 @@ pref("print.print_in_color", true);
 // fontconfig doesn't support emoji yet
 // https://lists.freedesktop.org/archives/fontconfig/2016-October/005842.html
 pref("font.name-list.emoji", "Twemoji Mozilla");
 
 pref("font.name-list.serif.ar", "serif");
 pref("font.name-list.sans-serif.ar", "sans-serif");
 pref("font.name-list.monospace.ar", "monospace");
 pref("font.name-list.cursive.ar", "cursive");
-pref("font.size.monospace.ar", 12);
+pref("font.size.fixed.ar", 12);
 
 pref("font.name-list.serif.el", "serif");
 pref("font.name-list.sans-serif.el", "sans-serif");
 pref("font.name-list.monospace.el", "monospace");
 pref("font.name-list.cursive.el", "cursive");
-pref("font.size.monospace.el", 12);
+pref("font.size.fixed.el", 12);
 
 pref("font.name-list.serif.he", "serif");
 pref("font.name-list.sans-serif.he", "sans-serif");
 pref("font.name-list.monospace.he", "monospace");
 pref("font.name-list.cursive.he", "cursive");
-pref("font.size.monospace.he", 12);
+pref("font.size.fixed.he", 12);
 
 pref("font.name-list.serif.ja", "serif");
 pref("font.name-list.sans-serif.ja", "sans-serif");
 pref("font.name-list.monospace.ja", "monospace");
 pref("font.name-list.cursive.ja", "cursive");
 
 pref("font.name-list.serif.ko", "serif");
 pref("font.name-list.sans-serif.ko", "sans-serif");
@@ -4466,17 +4466,17 @@ pref("font.name-list.serif.x-cans", "ser
 pref("font.name-list.sans-serif.x-cans", "sans-serif");
 pref("font.name-list.monospace.x-cans", "monospace");
 pref("font.name-list.cursive.x-cans", "cursive");
 
 pref("font.name-list.serif.x-cyrillic", "serif");
 pref("font.name-list.sans-serif.x-cyrillic", "sans-serif");
 pref("font.name-list.monospace.x-cyrillic", "monospace");
 pref("font.name-list.cursive.x-cyrillic", "cursive");
-pref("font.size.monospace.x-cyrillic", 12);
+pref("font.size.fixed.x-cyrillic", 12);
 
 pref("font.name-list.serif.x-devanagari", "serif");
 pref("font.name-list.sans-serif.x-devanagari", "sans-serif");
 pref("font.name-list.monospace.x-devanagari", "monospace");
 pref("font.name-list.cursive.x-devanagari", "cursive");
 
 pref("font.name-list.serif.x-ethi", "serif");
 pref("font.name-list.sans-serif.x-ethi", "sans-serif");
@@ -4537,23 +4537,23 @@ pref("font.name-list.serif.x-tibt", "ser
 pref("font.name-list.sans-serif.x-tibt", "sans-serif");
 pref("font.name-list.monospace.x-tibt", "monospace");
 pref("font.name-list.cursive.x-tibt", "cursive");
 
 pref("font.name-list.serif.x-unicode", "serif");
 pref("font.name-list.sans-serif.x-unicode", "sans-serif");
 pref("font.name-list.monospace.x-unicode", "monospace");
 pref("font.name-list.cursive.x-unicode", "cursive");
-pref("font.size.monospace.x-unicode", 12);
+pref("font.size.fixed.x-unicode", 12);
 
 pref("font.name-list.serif.x-western", "serif");
 pref("font.name-list.sans-serif.x-western", "sans-serif");
 pref("font.name-list.monospace.x-western", "monospace");
 pref("font.name-list.cursive.x-western", "cursive");
-pref("font.size.monospace.x-western", 12);
+pref("font.size.fixed.x-western", 12);
 
 pref("font.name-list.serif.zh-CN", "serif");
 pref("font.name-list.sans-serif.zh-CN", "sans-serif");
 pref("font.name-list.monospace.zh-CN", "monospace");
 pref("font.name-list.cursive.zh-CN", "cursive");
 
 pref("font.name-list.serif.zh-HK", "serif");
 pref("font.name-list.sans-serif.zh-HK", "sans-serif");
@@ -4597,31 +4597,31 @@ pref("gfx.font_rendering.fontconfig.max_
 
 # XP_UNIX
 #endif
 #endif
 #endif
 
 #if defined(ANDROID)
 
-pref("font.size.monospace.ar", 12);
+pref("font.size.fixed.ar", 12);
 
 pref("font.default.el", "sans-serif");
-pref("font.size.monospace.el", 12);
-
-pref("font.size.monospace.he", 12);
+pref("font.size.fixed.el", 12);
+
+pref("font.size.fixed.he", 12);
 
 pref("font.default.x-cyrillic", "sans-serif");
-pref("font.size.monospace.x-cyrillic", 12);
+pref("font.size.fixed.x-cyrillic", 12);
 
 pref("font.default.x-unicode", "sans-serif");
-pref("font.size.monospace.x-unicode", 12);
+pref("font.size.fixed.x-unicode", 12);
 
 pref("font.default.x-western", "sans-serif");
-pref("font.size.monospace.x-western", 12);
+pref("font.size.fixed.x-western", 12);
 
 # ANDROID
 #endif
 
 #if defined(ANDROID)
 // We use the bundled Charis SIL Compact as serif font for Firefox for Android
 
 pref("font.name-list.emoji", "Noto Color Emoji");
--- a/servo/components/style/font_metrics.rs
+++ b/servo/components/style/font_metrics.rs
@@ -38,17 +38,17 @@ pub trait FontMetricsProvider {
         _context: &crate::values::computed::Context,
         _base_size: crate::values::specified::length::FontBaseSize,
         _orientation: FontMetricsOrientation,
     ) -> FontMetrics {
         Default::default()
     }
 
     /// Get default size of a given language and generic family.
-    fn get_size(&self, font_name: &Atom, font_family: crate::values::computed::font::GenericFontFamily) -> Au;
+    fn get_size(&self, font_name: &Atom, font_family: u8) -> Au;
 
     /// Construct from a shared style context
     fn create_from(context: &SharedStyleContext) -> Self
     where
         Self: Sized;
 }
 
 // TODO: Servo's font metrics provider will probably not live in this crate, so this will
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -64,17 +64,16 @@ use crate::media_queries::Device;
 use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
 use crate::properties::{ComputedValues, LonghandId};
 use crate::properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
 use crate::rule_tree::CascadeLevel as ServoCascadeLevel;
 use crate::selector_parser::{AttrValue, HorizontalDirection, Lang};
 use crate::shared_lock::Locked;
 use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 use crate::stylist::CascadeData;
-use crate::values::computed::font::GenericFontFamily;
 use crate::values::specified::length::FontBaseSize;
 use crate::CaseSensitivityExt;
 use app_units::Au;
 use atomic_refcell::{AtomicRefCell, AtomicRefMut};
 use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator};
 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
 use selectors::matching::VisitedHandlingMode;
 use selectors::matching::{ElementSelectorFlags, MatchingContext};
@@ -1037,17 +1036,17 @@ impl GeckoFontMetricsProvider {
     }
 }
 
 impl FontMetricsProvider for GeckoFontMetricsProvider {
     fn create_from(_: &SharedStyleContext) -> GeckoFontMetricsProvider {
         GeckoFontMetricsProvider::new()
     }
 
-    fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Au {
+    fn get_size(&self, font_name: &Atom, font_family: u8) -> Au {
         let mut cache = self.font_size_cache.borrow_mut();
         if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
             return sizes.1.size_for_generic(font_family);
         }
         let sizes = unsafe { bindings::Gecko_GetBaseSize(font_name.as_ptr()) };
         cache.push((font_name.clone(), sizes));
         sizes.size_for_generic(font_family)
     }
@@ -1096,27 +1095,26 @@ impl FontMetricsProvider for GeckoFontMe
             } else {
                 None
             },
         }
     }
 }
 
 impl structs::FontSizePrefs {
-    fn size_for_generic(&self, font_family: GenericFontFamily) -> Au {
+    fn size_for_generic(&self, font_family: u8) -> Au {
         Au(match font_family {
-            GenericFontFamily::None => self.mDefaultVariableSize,
-            GenericFontFamily::Serif => self.mDefaultSerifSize,
-            GenericFontFamily::SansSerif => self.mDefaultSansSerifSize,
-            GenericFontFamily::Monospace => self.mDefaultMonospaceSize,
-            GenericFontFamily::Cursive => self.mDefaultCursiveSize,
-            GenericFontFamily::Fantasy => self.mDefaultFantasySize,
-            GenericFontFamily::MozEmoji => {
-                unreachable!("Should never get here, since this doesn't (yet) appear on font family")
-            },
+            structs::kPresContext_DefaultVariableFont_ID => self.mDefaultVariableSize,
+            structs::kPresContext_DefaultFixedFont_ID => self.mDefaultFixedSize,
+            structs::kGenericFont_serif => self.mDefaultSerifSize,
+            structs::kGenericFont_sans_serif => self.mDefaultSansSerifSize,
+            structs::kGenericFont_monospace => self.mDefaultMonospaceSize,
+            structs::kGenericFont_cursive => self.mDefaultCursiveSize,
+            structs::kGenericFont_fantasy => self.mDefaultFantasySize,
+            _ => unreachable!("Unknown generic ID"),
         })
     }
 }
 
 impl<'le> TElement for GeckoElement<'le> {
     type ConcreteNode = GeckoNode<'le>;
     type FontMetricsProvider = GeckoFontMetricsProvider;
     type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
--- a/servo/components/style/properties/cascade.rs
+++ b/servo/components/style/properties/cascade.rs
@@ -678,32 +678,31 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
     /// family, so we may need to recompute it if or the family changed.
     ///
     /// Also, we prioritize non-document fonts here if we need to (see the pref
     /// `browser.display.use_document_fonts`).
     #[inline]
     #[cfg(feature = "gecko")]
     fn recompute_default_font_family_type_if_needed(&mut self) {
         use crate::gecko_bindings::{bindings, structs};
-        use crate::values::computed::font::GenericFontFamily;
 
         if !self.seen.contains(LonghandId::XLang) &&
            !self.seen.contains(LonghandId::FontFamily) {
             return;
         }
 
         let use_document_fonts = unsafe { structs::StaticPrefs_sVarCache_browser_display_use_document_fonts != 0 };
         let builder = &mut self.context.builder;
         let (default_font_type, prioritize_user_fonts) = {
             let font = builder.get_font().gecko();
 
             // System fonts are all right, and should have the default font type
             // set to none already, so bail out early.
             if font.mFont.systemFont {
-                debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, GenericFontFamily::None);
+                debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, structs::FontFamilyType::eFamily_none);
                 return;
             }
 
             let default_font_type = unsafe {
                 bindings::Gecko_nsStyleFont_ComputeDefaultFontType(
                     builder.device.document(),
                     font.mGenericID,
                     font.mLanguage.mRawPtr,
@@ -713,21 +712,21 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
             // We prioritize user fonts over document fonts if the pref is set,
             // and we don't have a generic family already (or we're using
             // cursive or fantasy, since they're ignored, see bug 789788), and
             // we have a generic family to actually replace it with.
             let prioritize_user_fonts =
                 !use_document_fonts &&
                 matches!(
                     font.mGenericID,
-                    GenericFontFamily::None |
-                    GenericFontFamily::Fantasy |
-                    GenericFontFamily::Cursive
+                    structs::kGenericFont_NONE |
+                    structs::kGenericFont_fantasy |
+                    structs::kGenericFont_cursive
                 ) &&
-                default_font_type != GenericFontFamily::None;
+                default_font_type != structs::FontFamilyType::eFamily_none;
 
             if !prioritize_user_fonts && default_font_type == font.mFont.fontlist.mDefaultFontType {
                 // Nothing to do.
                 return;
             }
             (default_font_type, prioritize_user_fonts)
         };
 
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1979,50 +1979,70 @@ fn static_assert() {
     skip_longhands="${skip_font_longhands}">
 
     // Negative numbers are invalid at parse time, but <integer> is still an
     // i32.
     <% impl_font_settings("font_feature_settings", "gfxFontFeature", "FeatureTagValue", "i32", "u32") %>
     <% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %>
 
     pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
-        use crate::values::computed::font::GenericFontFamily;
+        use crate::gecko_bindings::structs::FontFamilyType;
 
         let is_system_font = v.is_system_font;
         self.gecko.mFont.systemFont = is_system_font;
         self.gecko.mGenericID = if is_system_font {
-            GenericFontFamily::None
+            structs::kGenericFont_NONE
         } else {
-            v.families.single_generic().unwrap_or(GenericFontFamily::None)
+            v.families.single_generic().unwrap_or(structs::kGenericFont_NONE)
         };
         self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move(
             v.families.shared_font_list().clone()
         );
         // Fixed-up if needed in Cascade::fixup_font_stuff.
-        self.gecko.mFont.fontlist.mDefaultFontType = GenericFontFamily::None;
+        self.gecko.mFont.fontlist.mDefaultFontType = FontFamilyType::eFamily_none;
     }
 
     pub fn copy_font_family_from(&mut self, other: &Self) {
         unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); }
         self.gecko.mGenericID = other.gecko.mGenericID;
         self.gecko.mFont.systemFont = other.gecko.mFont.systemFont;
     }
 
     pub fn reset_font_family(&mut self, other: &Self) {
         self.copy_font_family_from(other)
     }
 
     pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T {
+        use crate::gecko_bindings::structs::FontFamilyType;
         use crate::values::computed::font::{FontFamily, SingleFontFamily, FontFamilyList};
 
         let fontlist = &self.gecko.mFont.fontlist;
         let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() };
 
         let families = if shared_fontlist.mNames.is_empty() {
-            let default = SingleFontFamily::Generic(fontlist.mDefaultFontType);
+            let default = fontlist.mDefaultFontType;
+            let default = match default {
+                FontFamilyType::eFamily_serif => {
+                    SingleFontFamily::Generic(atom!("serif"))
+                }
+                _ => {
+                    // This can break with some combinations of user prefs, see
+                    // bug 1442195 for example. It doesn't really matter in this
+                    // case...
+                    //
+                    // FIXME(emilio): Probably should be storing the whole
+                    // default font name instead though.
+                    debug_assert_eq!(
+                        default,
+                        FontFamilyType::eFamily_sans_serif,
+                        "Default generic should be serif or sans-serif"
+                    );
+                    SingleFontFamily::Generic(atom!("sans-serif"))
+                }
+            };
             FontFamilyList::new(Box::new([default]))
         } else {
             FontFamilyList::SharedFontList(shared_fontlist)
         };
 
         FontFamily {
             families,
             is_system_font: self.gecko.mFont.systemFont,
--- a/servo/components/style/properties/longhands/font.mako.rs
+++ b/servo/components/style/properties/longhands/font.mako.rs
@@ -321,17 +321,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
         //!
         //! When a longhand property is holding a SystemFont, it's serialized
         //! to an empty string as if its value comes from a shorthand with
         //! variable reference. We may want to improve this behavior at some
         //! point. See also https://github.com/w3c/csswg-drafts/issues/1586.
 
         use app_units::Au;
         use cssparser::{Parser, ToCss};
-        use crate::values::computed::font::GenericFontFamily;
+        use crate::gecko_bindings::structs::FontFamilyType;
         use crate::properties::longhands;
         use std::fmt;
         use std::hash::{Hash, Hasher};
         use style_traits::ParseError;
         use crate::values::computed::{ToComputedValue, Context};
 
         <%
             system_fonts = """caption icon menu message-box small-caption status-bar
@@ -461,17 +461,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
         }
 
         #[derive(Clone, Debug)]
         pub struct ComputedSystemFont {
             % for name in SYSTEM_FONT_LONGHANDS:
                 pub ${name}: longhands::${name}::computed_value::T,
             % endfor
             pub system_font: SystemFont,
-            pub default_font_type: GenericFontFamily,
+            pub default_font_type: FontFamilyType,
         }
 
         impl SystemFont {
             pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
                 try_match_ident_ignore_ascii_case! { input,
                     % for font in system_fonts:
                         "${font}" => Ok(SystemFont::${to_camel_case(font)}),
                     % endfor
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -152,16 +152,20 @@ impl FontSize {
     pub fn medium() -> Self {
         Self {
             size: Au::from_px(specified::FONT_MEDIUM_PX).into(),
             keyword_info: Some(KeywordInfo::medium()),
         }
     }
 }
 
+/// XXXManishearth it might be better to
+/// animate this as computed, however this complicates
+/// clamping and might not be the right thing to do.
+/// We should figure it out.
 impl ToAnimatedValue for FontSize {
     type AnimatedValue = NonNegativeLength;
 
     #[inline]
     fn to_animated_value(self) -> Self::AnimatedValue {
         self.size
     }
 
@@ -169,32 +173,32 @@ impl ToAnimatedValue for FontSize {
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
         FontSize {
             size: animated.clamp(),
             keyword_info: None,
         }
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
-#[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf))]
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 /// Specifies a prioritized list of font family names or generic family names.
 pub struct FontFamily {
     /// The actual list of family names.
     pub families: FontFamilyList,
     /// Whether this font-family came from a specified system-font.
     pub is_system_font: bool,
 }
 
 impl FontFamily {
     #[inline]
     /// Get default font family as `serif` which is a generic font-family
     pub fn serif() -> Self {
         FontFamily {
-            families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(GenericFontFamily::Serif)])),
+            families: FontFamilyList::new(Box::new([SingleFontFamily::Generic(atom!("serif"))])),
             is_system_font: false,
         }
     }
 }
 
 #[cfg(feature = "gecko")]
 impl MallocSizeOf for FontFamily {
     fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
@@ -223,31 +227,31 @@ impl ToCss for FontFamily {
 
 #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// The name of a font family of choice
 pub struct FamilyName {
     /// Name of the font family
     pub name: Atom,
     /// Syntax of the font family
-    pub syntax: FontFamilyNameSyntax,
+    pub syntax: FamilyNameSyntax,
 }
 
 impl ToCss for FamilyName {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: fmt::Write,
     {
         match self.syntax {
-            FontFamilyNameSyntax::Quoted => {
+            FamilyNameSyntax::Quoted => {
                 dest.write_char('"')?;
                 write!(CssStringWriter::new(dest), "{}", self.name)?;
                 dest.write_char('"')
             },
-            FontFamilyNameSyntax::Identifiers => {
+            FamilyNameSyntax::Identifiers => {
                 let mut first = true;
                 for ident in self.name.to_string().split(' ') {
                     if first {
                         first = false;
                     } else {
                         dest.write_char(' ')?;
                     }
                     debug_assert!(
@@ -259,180 +263,305 @@ impl ToCss for FamilyName {
                     serialize_identifier(ident, dest)?;
                 }
                 Ok(())
             },
         }
     }
 }
 
-#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// Font family names must either be given quoted as strings,
 /// or unquoted as a sequence of one or more identifiers.
-#[repr(u8)]
-pub enum FontFamilyNameSyntax {
+pub enum FamilyNameSyntax {
     /// The family name was specified in a quoted form, e.g. "Font Name"
     /// or 'Font Name'.
     Quoted,
 
     /// The family name was specified in an unquoted form as a sequence of
     /// identifiers.
     Identifiers,
 }
 
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
-#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// A set of faces that vary in weight, width or slope.
 pub enum SingleFontFamily {
     /// The name of a font family of choice.
     FamilyName(FamilyName),
     /// Generic family name.
-    Generic(GenericFontFamily),
-}
-
-/// A generic font-family name.
-///
-/// The order here is important, if you change it make sure that
-/// `gfxPlatformFontList.h`s ranged array and `gfxFontFamilyList`'s
-/// sSingleGenerics are updated as well.
-#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss)]
-#[repr(u8)]
-#[allow(missing_docs)]
-pub enum GenericFontFamily {
-    /// No generic family specified, only for internal usage.
-    #[css(skip)]
-    None,
-    Serif,
-    SansSerif,
-    #[parse(aliases = "-moz-fixed")]
-    Monospace,
-    Cursive,
-    Fantasy,
-    /// An internal value for emoji font selection.
-    #[css(skip)]
-    #[cfg(feature = "gecko")]
-    MozEmoji,
+    Generic(Atom),
 }
 
 impl SingleFontFamily {
-    /// Parse a font-family value.
+    #[inline]
+    /// Get font family name as Atom
+    pub fn atom(&self) -> &Atom {
+        match *self {
+            SingleFontFamily::FamilyName(ref family_name) => &family_name.name,
+            SingleFontFamily::Generic(ref name) => name,
+        }
+    }
+
+    #[inline]
+    #[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
+    /// Get font family name
+    pub fn name(&self) -> &str {
+        self.atom()
+    }
+
+    #[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
+    /// Get the corresponding font-family with Atom
+    pub fn from_atom(input: Atom) -> SingleFontFamily {
+        match input {
+            atom!("serif") |
+            atom!("sans-serif") |
+            atom!("cursive") |
+            atom!("fantasy") |
+            atom!("monospace") => return SingleFontFamily::Generic(input),
+            _ => {},
+        }
+        match_ignore_ascii_case! { &input,
+            "serif" => return SingleFontFamily::Generic(atom!("serif")),
+            "sans-serif" => return SingleFontFamily::Generic(atom!("sans-serif")),
+            "cursive" => return SingleFontFamily::Generic(atom!("cursive")),
+            "fantasy" => return SingleFontFamily::Generic(atom!("fantasy")),
+            "monospace" => return SingleFontFamily::Generic(atom!("monospace")),
+            _ => {}
+        }
+
+        // We don't know if it's quoted or not. So we set it to
+        // quoted by default.
+        SingleFontFamily::FamilyName(FamilyName {
+            name: input,
+            syntax: FamilyNameSyntax::Quoted,
+        })
+    }
+
+    /// Parse a font-family value
     pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(value) = input.try(|i| i.expect_string_cloned()) {
             return Ok(SingleFontFamily::FamilyName(FamilyName {
                 name: Atom::from(&*value),
-                syntax: FontFamilyNameSyntax::Quoted,
+                syntax: FamilyNameSyntax::Quoted,
             }));
         }
+        let first_ident = input.expect_ident()?.clone();
 
-        let first_ident = input.expect_ident_cloned()?;
-        if let Ok(generic) = GenericFontFamily::from_ident(&first_ident) {
-            return Ok(SingleFontFamily::Generic(generic));
-        }
+        // FIXME(bholley): The fast thing to do here would be to look up the
+        // string (as lowercase) in the static atoms table. We don't have an
+        // API to do that yet though, so we do the simple thing for now.
+        let mut css_wide_keyword = false;
+        match_ignore_ascii_case! { &first_ident,
+            "serif" => return Ok(SingleFontFamily::Generic(atom!("serif"))),
+            "sans-serif" => return Ok(SingleFontFamily::Generic(atom!("sans-serif"))),
+            "cursive" => return Ok(SingleFontFamily::Generic(atom!("cursive"))),
+            "fantasy" => return Ok(SingleFontFamily::Generic(atom!("fantasy"))),
+            "monospace" => return Ok(SingleFontFamily::Generic(atom!("monospace"))),
 
-        let reserved = match_ignore_ascii_case! { &first_ident,
+            #[cfg(feature = "gecko")]
+            "-moz-fixed" => return Ok(SingleFontFamily::Generic(atom!("-moz-fixed"))),
+
             // https://drafts.csswg.org/css-fonts/#propdef-font-family
             // "Font family names that happen to be the same as a keyword value
             //  (`inherit`, `serif`, `sans-serif`, `monospace`, `fantasy`, and `cursive`)
             //  must be quoted to prevent confusion with the keywords with the same names.
             //  The keywords ‘initial’ and ‘default’ are reserved for future use
             //  and must also be quoted when used as font names.
             //  UAs must not consider these keywords as matching the <family-name> type."
-            "inherit" | "initial" | "unset" | "revert" | "default" => true,
-            _ => false,
-        };
+            "inherit" => css_wide_keyword = true,
+            "initial" => css_wide_keyword = true,
+            "unset" => css_wide_keyword = true,
+            "default" => css_wide_keyword = true,
+            _ => {}
+        }
 
         let mut value = first_ident.as_ref().to_owned();
 
         // These keywords are not allowed by themselves.
         // The only way this value can be valid with with another keyword.
-        if reserved {
+        if css_wide_keyword {
             let ident = input.expect_ident()?;
             value.push(' ');
             value.push_str(&ident);
         }
         while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) {
             value.push(' ');
             value.push_str(&ident);
         }
         let syntax = if value.starts_with(' ') || value.ends_with(' ') || value.contains("  ") {
             // For font family names which contains special white spaces, e.g.
             // `font-family: \ a\ \ b\ \ c\ ;`, it is tricky to serialize them
             // as identifiers correctly. Just mark them quoted so we don't need
             // to worry about them in serialization code.
-            FontFamilyNameSyntax::Quoted
+            FamilyNameSyntax::Quoted
         } else {
-            FontFamilyNameSyntax::Identifiers
+            FamilyNameSyntax::Identifiers
         };
         Ok(SingleFontFamily::FamilyName(FamilyName {
             name: Atom::from(value),
             syntax,
         }))
     }
 
     #[cfg(feature = "gecko")]
+    /// Return the generic ID for a given generic font name
+    pub fn generic(name: &Atom) -> (structs::FontFamilyType, u8) {
+        use crate::gecko_bindings::structs::FontFamilyType;
+        if *name == atom!("serif") {
+            (FontFamilyType::eFamily_serif, structs::kGenericFont_serif)
+        } else if *name == atom!("sans-serif") {
+            (
+                FontFamilyType::eFamily_sans_serif,
+                structs::kGenericFont_sans_serif,
+            )
+        } else if *name == atom!("cursive") {
+            (
+                FontFamilyType::eFamily_cursive,
+                structs::kGenericFont_cursive,
+            )
+        } else if *name == atom!("fantasy") {
+            (
+                FontFamilyType::eFamily_fantasy,
+                structs::kGenericFont_fantasy,
+            )
+        } else if *name == atom!("monospace") {
+            (
+                FontFamilyType::eFamily_monospace,
+                structs::kGenericFont_monospace,
+            )
+        } else if *name == atom!("-moz-fixed") {
+            (
+                FontFamilyType::eFamily_moz_fixed,
+                structs::kGenericFont_moz_fixed,
+            )
+        } else {
+            panic!("Unknown generic {}", name);
+        }
+    }
+
+    #[cfg(feature = "gecko")]
     /// Get the corresponding font-family with family name
     fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily {
-        if family.mName.mRawPtr.is_null() {
-            debug_assert_ne!(family.mGeneric, GenericFontFamily::None);
-            return SingleFontFamily::Generic(family.mGeneric);
+        use crate::gecko_bindings::structs::FontFamilyType;
+
+        match family.mType {
+            FontFamilyType::eFamily_sans_serif => SingleFontFamily::Generic(atom!("sans-serif")),
+            FontFamilyType::eFamily_serif => SingleFontFamily::Generic(atom!("serif")),
+            FontFamilyType::eFamily_monospace => SingleFontFamily::Generic(atom!("monospace")),
+            FontFamilyType::eFamily_cursive => SingleFontFamily::Generic(atom!("cursive")),
+            FontFamilyType::eFamily_fantasy => SingleFontFamily::Generic(atom!("fantasy")),
+            FontFamilyType::eFamily_moz_fixed => SingleFontFamily::Generic(atom!("-moz-fixed")),
+            FontFamilyType::eFamily_named => {
+                let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
+                SingleFontFamily::FamilyName(FamilyName {
+                    name,
+                    syntax: FamilyNameSyntax::Identifiers,
+                })
+            },
+            FontFamilyType::eFamily_named_quoted => {
+                let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
+                SingleFontFamily::FamilyName(FamilyName {
+                    name,
+                    syntax: FamilyNameSyntax::Quoted,
+                })
+            },
+            _ => panic!("Found unexpected font FontFamilyType"),
         }
-        let name = unsafe { Atom::from_raw(family.mName.mRawPtr) };
-        SingleFontFamily::FamilyName(FamilyName {
-            name,
-            syntax: family.mSyntax,
-        })
+    }
+}
+
+impl ToCss for SingleFontFamily {
+    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+    where
+        W: fmt::Write,
+    {
+        match *self {
+            SingleFontFamily::FamilyName(ref name) => name.to_css(dest),
+
+            // All generic values accepted by the parser are known to not require escaping.
+            SingleFontFamily::Generic(ref name) => {
+                #[cfg(feature = "gecko")]
+                {
+                    // We should treat -moz-fixed as monospace
+                    if name == &atom!("-moz-fixed") {
+                        return dest.write_str("monospace");
+                    }
+                }
+
+                write!(dest, "{}", name)
+            },
+        }
     }
 }
 
 #[cfg(feature = "servo")]
 #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
 /// A list of SingleFontFamily
 pub struct FontFamilyList(Box<[SingleFontFamily]>);
 
 #[cfg(feature = "gecko")]
 #[derive(Clone, Debug)]
 /// A list of SingleFontFamily
 pub enum FontFamilyList {
     /// A strong reference to a Gecko SharedFontList object.
     SharedFontList(RefPtr<structs::SharedFontList>),
     /// A font-family generic ID.
-    Generic(GenericFontFamily),
+    Generic(structs::FontFamilyType),
 }
 
 #[cfg(feature = "gecko")]
 impl ToShmem for FontFamilyList {
     fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> ManuallyDrop<Self> {
         // In practice, the only SharedFontList objects we create from shared
         // style sheets are ones with a single generic entry.
-        ManuallyDrop::new(match *self {
-            FontFamilyList::SharedFontList(ref r) => {
+        ManuallyDrop::new(match self {
+            FontFamilyList::SharedFontList(r) => {
                 assert!(
                     r.mNames.len() == 1 && r.mNames[0].mName.mRawPtr.is_null(),
                     "ToShmem failed for FontFamilyList: cannot handle non-generic families",
                 );
-                FontFamilyList::Generic(r.mNames[0].mGeneric)
+                FontFamilyList::Generic(r.mNames[0].mType)
             },
-            FontFamilyList::Generic(t) => FontFamilyList::Generic(t),
+            FontFamilyList::Generic(t) => FontFamilyList::Generic(*t),
         })
     }
 }
 
 #[cfg(feature = "gecko")]
+impl Hash for FontFamilyList {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        use crate::string_cache::WeakAtom;
+
+        for name in self.shared_font_list().mNames.iter() {
+            name.mType.hash(state);
+            if !name.mName.mRawPtr.is_null() {
+                unsafe {
+                    WeakAtom::new(name.mName.mRawPtr).hash(state);
+                }
+            }
+        }
+    }
+}
+
+#[cfg(feature = "gecko")]
 impl PartialEq for FontFamilyList {
     fn eq(&self, other: &FontFamilyList) -> bool {
         let self_list = self.shared_font_list();
         let other_list = other.shared_font_list();
 
         if self_list.mNames.len() != other_list.mNames.len() {
             return false;
         }
         for (a, b) in self_list.mNames.iter().zip(other_list.mNames.iter()) {
-            if a.mSyntax != b.mSyntax || a.mName.mRawPtr != b.mName.mRawPtr ||
-                a.mGeneric != b.mGeneric {
+            if a.mType != b.mType || a.mName.mRawPtr != b.mName.mRawPtr {
                 return false;
             }
         }
         true
     }
 }
 
 #[cfg(feature = "gecko")]
@@ -454,27 +583,29 @@ impl FontFamilyList {
             fontlist = bindings::Gecko_SharedFontList_Create();
             names = &mut (*fontlist).mNames;
             names.ensure_capacity(families.len());
         };
 
         for family in families.iter() {
             match *family {
                 SingleFontFamily::FamilyName(ref f) => {
+                    let quoted = matches!(f.syntax, FamilyNameSyntax::Quoted);
                     unsafe {
                         bindings::Gecko_nsTArray_FontFamilyName_AppendNamed(
                             names,
                             f.name.as_ptr(),
-                            f.syntax,
+                            quoted,
                         );
                     }
                 },
-                SingleFontFamily::Generic(family) => {
+                SingleFontFamily::Generic(ref name) => {
+                    let (family_type, _generic) = SingleFontFamily::generic(name);
                     unsafe {
-                        bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family);
+                        bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family_type);
                     }
                 },
             }
         }
 
         FontFamilyList::SharedFontList(unsafe { RefPtr::from_addrefed(fontlist) })
     }
 
@@ -489,35 +620,37 @@ impl FontFamilyList {
     pub fn iter(&self) -> FontFamilyNameIter {
         FontFamilyNameIter {
             names: &self.shared_font_list().mNames,
             cur: 0,
         }
     }
 
     /// Return the generic ID if it is a single generic font
-    pub fn single_generic(&self) -> Option<GenericFontFamily> {
+    #[cfg(feature = "gecko")]
+    pub fn single_generic(&self) -> Option<u8> {
         let mut iter = self.iter();
-        if let Some(SingleFontFamily::Generic(f)) = iter.next() {
+        if let Some(SingleFontFamily::Generic(ref name)) = iter.next() {
             if iter.next().is_none() {
-                return Some(f);
+                return Some(SingleFontFamily::generic(name).1);
             }
         }
         None
     }
 
     /// Return a reference to the Gecko SharedFontList.
     #[cfg(feature = "gecko")]
     pub fn shared_font_list(&self) -> &RefPtr<structs::SharedFontList> {
-        match *self {
-            FontFamilyList::SharedFontList(ref r) => r,
+        match self {
+            FontFamilyList::SharedFontList(r) => r,
             FontFamilyList::Generic(t) => {
                 unsafe {
                     // TODO(heycam): Should really add StaticRefPtr sugar.
-                    let index = t as usize;
+                    let index =
+                        (*t as usize) - (structs::FontFamilyType::eFamily_generic_first as usize);
                     mem::transmute::<
                         &structs::StaticRefPtr<structs::SharedFontList>,
                         &RefPtr<structs::SharedFontList>,
                     >(&structs::SharedFontList_sSingleGenerics[index])
                 }
             },
         }
     }
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -510,34 +510,43 @@ pub enum FontSize {
 
 impl From<LengthPercentage> for FontSize {
     fn from(other: LengthPercentage) -> Self {
         FontSize::Length(other)
     }
 }
 
 /// Specifies a prioritized list of font family names or generic family names.
-#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
-#[cfg_attr(feature = "servo", derive(Hash))]
+#[derive(Clone, Debug, Eq, Hash, PartialEq, ToCss, ToShmem)]
 pub enum FontFamily {
     /// List of `font-family`
     #[css(comma)]
     Values(#[css(iterable)] FontFamilyList),
     /// System font
     #[css(skip)]
     System(SystemFont),
 }
 
 impl FontFamily {
     system_font_methods!(FontFamily, font_family);
 
     /// Parse a specified font-family value
     pub fn parse_specified<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        let values = input.parse_comma_separated(SingleFontFamily::parse)?;
-        Ok(FontFamily::Values(FontFamilyList::new(values.into_boxed_slice())))
+        input
+            .parse_comma_separated(|input| SingleFontFamily::parse(input))
+            .map(|v| FontFamily::Values(FontFamilyList::new(v.into_boxed_slice())))
+    }
+
+    #[cfg(feature = "gecko")]
+    /// Return the generic ID if it is a single generic font
+    pub fn single_generic(&self) -> Option<u8> {
+        match *self {
+            FontFamily::Values(ref values) => values.single_generic(),
+            _ => None,
+        }
     }
 }
 
 impl ToComputedValue for FontFamily {
     type ComputedValue = computed::FontFamily;
 
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
         match *self {
--- a/servo/ports/geckolib/cbindgen.toml
+++ b/servo/ports/geckolib/cbindgen.toml
@@ -56,18 +56,16 @@ include = [
   "Display",
   "DisplayMode",
   "PrefersColorScheme",
   "ExtremumLength",
   "FillRule",
   "FontDisplay",
   "FontFaceSourceListComponent",
   "FontLanguageOverride",
-  "GenericFontFamily",
-  "FontFamilyNameSyntax",
   "OverflowWrap",
   "TimingFunction",
   "PathCommand",
   "UnicodeRange",
   "UserSelect",
   "Float",
   "OverscrollBehavior",
   "ScrollSnapAlign",