Bug 1283932 - support COLR table layers with unset color, r=jfkthame
authorKhaled Hosny <khaledhosny@eglug.org>
Wed, 06 Jul 2016 10:10:17 +0100
changeset 331200 e666f640f6434593a6077b4dc24e96bfdf868166
parent 331199 1fecbe3e55c98eca2ba43600fad3db357e3eca60
child 331201 d2c74a5856983742da3d22209637ff483ee5e83c
push idunknown
push userunknown
push dateunknown
reviewersjfkthame
bugs1283932
milestone50.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 1283932 - support COLR table layers with unset color, r=jfkthame
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxFontEntry.cpp
gfx/thebes/gfxFontEntry.h
gfx/thebes/gfxFontUtils.cpp
gfx/thebes/gfxFontUtils.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1781,17 +1781,17 @@ gfxFont::DrawOneGlyph(uint32_t aGlyphID,
         if (RenderSVGGlyph(runParams.context, devPt,
                            aGlyphID, fontParams.contextPaint,
                            runParams.callbacks, *aEmittedGlyphs)) {
             return;
         }
     }
 
     if (fontParams.haveColorGlyphs &&
-        RenderColorGlyph(runParams.dt,
+        RenderColorGlyph(runParams.dt, runParams.context,
                          fontParams.scaledFont, fontParams.renderingOptions,
                          fontParams.drawOptions,
                          fontParams.matInv * gfx::Point(devPt.x, devPt.y),
                          aGlyphID)) {
         return;
     }
 
     aBuffer.OutputGlyph(aGlyphID, devPt);
@@ -2165,26 +2165,32 @@ gfxFont::RenderSVGGlyph(gfxContext *aCon
         aCallbacks->NotifyGlyphPathEmitted();
         aEmittedGlyphs = false;
     }
     return RenderSVGGlyph(aContext, aPoint, aGlyphId, aContextPaint);
 }
 
 bool
 gfxFont::RenderColorGlyph(DrawTarget* aDrawTarget,
+                          gfxContext* aContext,
                           mozilla::gfx::ScaledFont* scaledFont,
                           GlyphRenderingOptions* aRenderingOptions,
                           mozilla::gfx::DrawOptions aDrawOptions,
                           const mozilla::gfx::Point& aPoint,
                           uint32_t aGlyphId) const
 {
     AutoTArray<uint16_t, 8> layerGlyphs;
     AutoTArray<mozilla::gfx::Color, 8> layerColors;
 
-    if (!GetFontEntry()->GetColorLayersInfo(aGlyphId, layerGlyphs, layerColors)) {
+    mozilla::gfx::Color defaultColor;
+    if (!aContext->GetDeviceColor(defaultColor)) {
+        defaultColor = mozilla::gfx::Color(0, 0, 0);
+    }
+    if (!GetFontEntry()->GetColorLayersInfo(aGlyphId, defaultColor,
+                                            layerGlyphs, layerColors)) {
         return false;
     }
 
     for (uint32_t layerIndex = 0; layerIndex < layerGlyphs.Length();
          layerIndex++) {
         Glyph glyph;
         glyph.mIndex = layerGlyphs[layerIndex];
         glyph.mPosition = aPoint;
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -2150,16 +2150,17 @@ protected:
     bool RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint,
                         uint32_t aGlyphId, gfxTextContextPaint *aContextPaint) const;
     bool RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint,
                         uint32_t aGlyphId, gfxTextContextPaint *aContextPaint,
                         gfxTextRunDrawCallbacks *aCallbacks,
                         bool& aEmittedGlyphs) const;
 
     bool RenderColorGlyph(DrawTarget* aDrawTarget,
+                          gfxContext* aContext,
                           mozilla::gfx::ScaledFont* scaledFont,
                           mozilla::gfx::GlyphRenderingOptions* renderingOptions,
                           mozilla::gfx::DrawOptions drawOptions,
                           const mozilla::gfx::Point& aPoint,
                           uint32_t aGlyphId) const;
 
     // Bug 674909. When synthetic bolding text by drawing twice, need to
     // render using a pixel offset in device pixels, otherwise text
--- a/gfx/thebes/gfxFontEntry.cpp
+++ b/gfx/thebes/gfxFontEntry.cpp
@@ -1057,22 +1057,24 @@ gfxFontEntry::SupportsGraphiteFeature(ui
 
     mSupportedFeatures->Put(scriptFeature, result);
 
     return result;
 }
 
 bool
 gfxFontEntry::GetColorLayersInfo(uint32_t aGlyphId,
+                            const mozilla::gfx::Color& aDefaultColor,
                             nsTArray<uint16_t>& aLayerGlyphs,
                             nsTArray<mozilla::gfx::Color>& aLayerColors)
 {
     return gfxFontUtils::GetColorGlyphLayers(mCOLR,
                                              mCPAL,
                                              aGlyphId,
+                                             aDefaultColor,
                                              aLayerGlyphs,
                                              aLayerColors);
 }
 
 size_t
 gfxFontEntry::FontTableHashEntry::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
     size_t n = 0;
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -260,16 +260,17 @@ public:
                                       gfxFloat* aItalicCorrection);
     uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
                                  uint16_t aSize);
     bool     GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
                                   uint32_t aGlyphs[4]);
 
     bool     TryGetColorGlyphs();
     bool     GetColorLayersInfo(uint32_t aGlyphId,
+                                const mozilla::gfx::Color& aDefaultColor,
                                 nsTArray<uint16_t>& layerGlyphs,
                                 nsTArray<mozilla::gfx::Color>& layerColors);
 
     virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
         return true;
     }
     virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
         return true;
--- a/gfx/thebes/gfxFontUtils.cpp
+++ b/gfx/thebes/gfxFontUtils.cpp
@@ -1664,17 +1664,18 @@ gfxFontUtils::ValidateColorGlyphs(hb_blo
         }
     }
 
     const COLRLayerRecord* layer =
         reinterpret_cast<const COLRLayerRecord*>(
             reinterpret_cast<const uint8_t*>(colr) + offsetLayerRecord);
 
     for (uint16_t i = 0; i < numLayerRecords; i++, layer++) {
-        if (uint16_t(layer->paletteEntryIndex) >= numPaletteEntries) {
+        if (uint16_t(layer->paletteEntryIndex) >= numPaletteEntries &&
+            uint16_t(layer->paletteEntryIndex) != 0xFFFF) {
             // CPAL palette entry record is overflow
             return false;
         }
     }
 
     return true;
 }
 
@@ -1708,16 +1709,17 @@ LookForBaseGlyphRecord(const COLRHeader*
                        sizeof(COLRBaseGlyphRecord),
                        CompareBaseGlyph));
 }
 
 bool
 gfxFontUtils::GetColorGlyphLayers(hb_blob_t* aCOLR,
                                   hb_blob_t* aCPAL,
                                   uint32_t aGlyphId,
+                                  const mozilla::gfx::Color& aDefaultColor,
                                   nsTArray<uint16_t>& aGlyphs,
                                   nsTArray<mozilla::gfx::Color>& aColors)
 {
     unsigned int blobLength;
     const COLRHeader* colr =
         reinterpret_cast<const COLRHeader*>(hb_blob_get_data(aCOLR,
                                                              &blobLength));
     MOZ_ASSERT(colr, "Cannot get COLR raw data");
@@ -1739,25 +1741,29 @@ gfxFontUtils::GetColorGlyphLayers(hb_blo
             reinterpret_cast<const uint8_t*>(colr) +
             uint32_t(colr->offsetLayerRecord) +
             sizeof(COLRLayerRecord) * uint16_t(baseGlyph->firstLayerIndex));
     const uint16_t numLayers = baseGlyph->numLayers;
     const uint32_t offsetFirstColorRecord = cpal->offsetFirstColorRecord;
 
     for (uint16_t layerIndex = 0; layerIndex < numLayers; layerIndex++) {
         aGlyphs.AppendElement(uint16_t(layer->glyphId));
-        const CPALColorRecord* color =
-            reinterpret_cast<const CPALColorRecord*>(
-                reinterpret_cast<const uint8_t*>(cpal) +
-                offsetFirstColorRecord +
-                sizeof(CPALColorRecord) * uint16_t(layer->paletteEntryIndex));
-        aColors.AppendElement(mozilla::gfx::Color(color->red / 255.0,
-                                                  color->green / 255.0,
-                                                  color->blue / 255.0,
-                                                  color->alpha / 255.0));
+        if (uint16_t(layer->paletteEntryIndex) == 0xFFFF) {
+            aColors.AppendElement(aDefaultColor);
+        } else {
+            const CPALColorRecord* color =
+                reinterpret_cast<const CPALColorRecord*>(
+                    reinterpret_cast<const uint8_t*>(cpal) +
+                    offsetFirstColorRecord +
+                    sizeof(CPALColorRecord) * uint16_t(layer->paletteEntryIndex));
+            aColors.AppendElement(mozilla::gfx::Color(color->red / 255.0,
+                                                      color->green / 255.0,
+                                                      color->blue / 255.0,
+                                                      color->alpha / 255.0));
+        }
         layer++;
     }
     return true;
 }
 
 #ifdef XP_WIN
 
 /* static */
--- a/gfx/thebes/gfxFontUtils.h
+++ b/gfx/thebes/gfxFontUtils.h
@@ -974,16 +974,17 @@ public:
     // generate a unique font name
     static nsresult MakeUniqueUserFontName(nsAString& aName);
 
     // for color layer from glyph using COLR and CPAL tables
     static bool ValidateColorGlyphs(hb_blob_t* aCOLR, hb_blob_t* aCPAL);
     static bool GetColorGlyphLayers(hb_blob_t* aCOLR,
                                     hb_blob_t* aCPAL,
                                     uint32_t aGlyphId,
+                                    const mozilla::gfx::Color& aDefaultColor,
                                     nsTArray<uint16_t> &aGlyphs,
                                     nsTArray<mozilla::gfx::Color> &aColors);
 
 protected:
     friend struct MacCharsetMappingComparator;
 
     static nsresult
     ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID,