Bug 1427641 - patch 4 - For downloadable fonts that have variations, create a separate FT_Face for each instance used. r=lsalzman
authorJonathan Kew <jkew@mozilla.com>
Sun, 10 Dec 2017 14:01:32 +0000
changeset 449886 d6e329f15f6ab2ca85c7daef5ce0370a1327cd00
parent 449885 54896137200d457c307690840e1efa02b7567466
child 449887 78fe966a5d43de3b05066a0da697baa960c6fd3f
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1427641
milestone59.0a1
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
Bug 1427641 - patch 4 - For downloadable fonts that have variations, create a separate FT_Face for each instance used. r=lsalzman
gfx/thebes/gfxFcPlatformFontList.cpp
gfx/thebes/gfxFcPlatformFontList.h
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -224,17 +224,17 @@ MapFcWidth(int aFcWidth)
 }
 
 gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
                                                FcPattern* aFontPattern,
                                                bool aIgnoreFcCharmap)
         : gfxFontEntry(aFaceName), mFontPattern(aFontPattern),
           mFTFace(nullptr), mFTFaceInitialized(false),
           mIgnoreFcCharmap(aIgnoreFcCharmap),
-          mAspect(0.0), mFontData(nullptr)
+          mAspect(0.0), mFontData(nullptr), mLength(0)
 {
     // italic
     int slant;
     if (FcPatternGetInteger(aFontPattern, FC_SLANT, 0, &slant) != FcResultMatch) {
         slant = FC_SLANT_ROMAN;
     }
     if (slant == FC_SLANT_OBLIQUE) {
         mStyle = NS_FONT_STYLE_OBLIQUE;
@@ -264,21 +264,22 @@ gfxFontconfigFontEntry::Clone() const
     return new gfxFontconfigFontEntry(Name(), mFontPattern, mIgnoreFcCharmap);
 }
 
 gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
                                                uint16_t aWeight,
                                                int16_t aStretch,
                                                uint8_t aStyle,
                                                const uint8_t *aData,
+                                               uint32_t aLength,
                                                FT_Face aFace)
     : gfxFontEntry(aFaceName),
       mFTFace(aFace), mFTFaceInitialized(true),
       mIgnoreFcCharmap(true),
-      mAspect(0.0), mFontData(aData)
+      mAspect(0.0), mFontData(aData), mLength(aLength)
 {
     mWeight = aWeight;
     mStyle = aStyle;
     mStretch = aStretch;
     mIsDataUserFont = true;
 
     // Use fontconfig to fill out the pattern from the FTFace.
     // The "file" argument cannot be nullptr (in fontconfig-2.6.0 at
@@ -307,17 +308,17 @@ gfxFontconfigFontEntry::gfxFontconfigFon
 
 gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
                                                FcPattern* aFontPattern,
                                                uint16_t aWeight,
                                                int16_t aStretch,
                                                uint8_t aStyle)
         : gfxFontEntry(aFaceName), mFontPattern(aFontPattern),
           mFTFace(nullptr), mFTFaceInitialized(false),
-          mAspect(0.0), mFontData(nullptr)
+          mAspect(0.0), mFontData(nullptr), mLength(0)
 {
     mWeight = aWeight;
     mStyle = aStyle;
     mStretch = aStretch;
     mIsLocalUserFont = true;
 
     // The proper setting of mIgnoreFcCharmap is tricky for fonts loaded
     // via src:local()...
@@ -893,19 +894,43 @@ gfxFontconfigFontEntry::CreateFontInstan
     if (!pattern) {
         NS_WARNING("Failed to create Fontconfig pattern for font instance");
         return nullptr;
     }
 
     double size = ChooseFontSize(this, *aFontStyle);
     FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size);
 
+    FT_Face face = mFTFace; // may be null, if it's not a user font
+    FcPattern* fontPattern = mFontPattern;
+    if (mFontData) {
+        MOZ_ASSERT(face, "face should not be null for user font");
+        if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
+            // For variation fonts, we create a new FT_Face and FcPattern
+            // so that variation coordinates from the style can be applied
+            // without affecting other font instances created from the same
+            // entry (font resource).
+            face = Factory::NewFTFaceFromData(nullptr, mFontData, mLength, 0);
+            fontPattern = FcFreeTypeQueryFace(face, ToFcChar8Ptr(""), 0, nullptr);
+            if (!fontPattern) {
+                fontPattern = FcPatternCreate();
+            }
+            FcPatternDel(fontPattern, FC_FILE);
+            FcPatternDel(fontPattern, FC_INDEX);
+            FcPatternAddFTFace(fontPattern, FC_FT_FACE, face);
+        }
+    }
+
     PreparePattern(pattern, aFontStyle->printerFont);
     nsAutoRef<FcPattern> renderPattern
-        (FcFontRenderPrepare(nullptr, pattern, mFontPattern));
+        (FcFontRenderPrepare(nullptr, pattern, fontPattern));
+    if (fontPattern != mFontPattern) {
+        // Discard temporary pattern used for variation support
+        FcPatternDestroy(fontPattern);
+    }
     if (!renderPattern) {
         NS_WARNING("Failed to prepare Fontconfig pattern for font instance");
         return nullptr;
     }
 
     cairo_scaled_font_t* scaledFont =
         CreateScaledFont(renderPattern, size, aFontStyle, aNeedsBold);
 
@@ -920,17 +945,17 @@ gfxFontconfigFontEntry::CreateFontInstan
         }
     }
 
     RefPtr<UnscaledFontFontconfig> unscaledFont =
         mUnscaledFontCache.Lookup(ToCharPtr(file), index);
     if (!unscaledFont) {
         unscaledFont =
             mFontData ?
-                new UnscaledFontFontconfig(mFTFace) :
+                new UnscaledFontFontconfig(face) :
                 new UnscaledFontFontconfig(ToCharPtr(file), index);
         mUnscaledFontCache.Add(unscaledFont);
     }
 
     gfxFont* newFont =
         new gfxFontconfigFont(unscaledFont, scaledFont,
                               renderPattern, size,
                               this, aFontStyle, aNeedsBold);
@@ -1700,17 +1725,17 @@ gfxFcPlatformFontList::MakePlatformFont(
     }
     if (FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_UNICODE)) {
         Factory::ReleaseFTFace(face);
         free((void*)aFontData);
         return nullptr;
     }
 
     return new gfxFontconfigFontEntry(aFontName, aWeight, aStretch,
-                                      aStyle, aFontData, face);
+                                      aStyle, aFontData, aLength, face);
 }
 
 bool
 gfxFcPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
                                           nsTArray<gfxFontFamily*>* aOutput,
                                           FindFamiliesFlags aFlags,
                                           gfxFontStyle* aStyle,
                                           gfxFloat aDevToCssSize)
--- a/gfx/thebes/gfxFcPlatformFontList.h
+++ b/gfx/thebes/gfxFcPlatformFontList.h
@@ -91,16 +91,17 @@ public:
 
     // used for data fonts where the fontentry takes ownership
     // of the font data and the FT_Face
     explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
                                     uint16_t aWeight,
                                     int16_t aStretch,
                                     uint8_t aStyle,
                                     const uint8_t *aData,
+                                    uint32_t aLength,
                                     FT_Face aFace);
 
     // used for @font-face local system fonts with explicit patterns
     explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
                                     FcPattern* aFontPattern,
                                     uint16_t aWeight,
                                     int16_t aStretch,
                                     uint8_t aStyle);
@@ -158,16 +159,17 @@ protected:
     // include color glyphs that fontconfig would overlook, and for fonts
     // loaded via @font-face.
     bool      mIgnoreFcCharmap;
 
     double    mAspect;
 
     // data font
     const uint8_t* mFontData;
+    uint32_t       mLength;
 
     class UnscaledFontCache
     {
     public:
         already_AddRefed<mozilla::gfx::UnscaledFontFontconfig>
         Lookup(const char* aFile, uint32_t aIndex);
 
         void Add(const RefPtr<mozilla::gfx::UnscaledFontFontconfig>& aUnscaledFont) {