Fix color emoji.
authorjvanverth <jvanverth@google.com>
Fri, 10 Oct 2014 18:36:12 +0000 (11:36 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 10 Oct 2014 18:36:12 +0000 (11:36 -0700)
Removes the GrMaskFormat and single atlas in GrTextStrike.
Replaces it by storing the GrMaskFormat in each GrGlyph, and
doing a lookup for the correct atlas based on that.

Disables color glyph rendering in GrDistanceFieldTextContext
for now.

BUG=skia:2887

Committed: https://skia.googlesource.com/skia/+/bc92163ddfe957ad6ffbb02ac40e0ba75ff82216

Review URL: https://codereview.chromium.org/636183005

expectations/gm/ignored-tests.txt
include/gpu/GrFontScaler.h
include/gpu/GrGlyph.h
src/gpu/GrAtlas.cpp
src/gpu/GrBitmapTextContext.cpp
src/gpu/GrBitmapTextContext.h
src/gpu/GrDistanceFieldTextContext.cpp
src/gpu/GrFontScaler.cpp
src/gpu/GrTextStrike.cpp
src/gpu/GrTextStrike.h

index 5793ba217bb71761725687932327c317b11cd80c..27182c904afc2f11ccd9a4c4ad69609083b7ed74 100644 (file)
 ## epoger will rebaseline by 25 Dec 2013
 #gradtext
 
+# jvanverth
+# color emoji fix
+coloremoji
+
 # rileya - https://codereview.chromium.org/516463005/ will rebaseline after bots cycle
 yuv_to_rgb_effect
 
index 037603813561bd59f2997235e4f6383422b61825..54d1e3f9cca39162719cc4594a80291a2902e9dc 100644 (file)
@@ -66,7 +66,8 @@ public:
     virtual ~GrFontScaler();
     
     const GrFontDescKey* getKey();
-    GrMaskFormat getMaskFormat();
+    GrMaskFormat getMaskFormat() const;
+    GrMaskFormat getPackedGlyphMaskFormat(GrGlyph::PackedID) const;
     bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds);
     bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
                                      int rowBytes, void* image);
index a379144a4289067c572ded56d9462ecff5d01abd..0e534d694afe1fb7c1ef2b518d83938c4910a0bf 100644 (file)
@@ -9,8 +9,10 @@
 #define GrGlyph_DEFINED
 
 #include "GrRect.h"
-#include "SkPath.h"
+#include "GrTypes.h"
+
 #include "SkChecksum.h"
+#include "SkPath.h"
 
 class GrPlot;
 
@@ -23,17 +25,19 @@ class GrPlot;
 struct GrGlyph {
     typedef uint32_t PackedID;
 
-    GrPlot*     fPlot;
-    SkPath*     fPath;
-    PackedID    fPackedID;
-    GrIRect16   fBounds;
-    SkIPoint16  fAtlasLocation;
+    GrPlot*      fPlot;
+    SkPath*      fPath;
+    PackedID     fPackedID;
+    GrMaskFormat fMaskFormat;
+    GrIRect16    fBounds;
+    SkIPoint16   fAtlasLocation;
 
-    void init(GrGlyph::PackedID packed, const SkIRect& bounds) {
+    void init(GrGlyph::PackedID packed, const SkIRect& bounds, GrMaskFormat format) {
         fPlot = NULL;
         fPath = NULL;
         fPackedID = packed;
         fBounds.set(bounds);
+        fMaskFormat = format;
         fAtlasLocation.set(0, 0);
     }
 
index e75f859fec5e3bea4e3498101593cd32a7004a88..0491eeda02ecfe1870199327634630080122dde7 100644 (file)
@@ -216,7 +216,8 @@ GrPlot* GrAtlas::addToAtlas(ClientPlotUsage* usage,
     // last one was most recently added and probably most empty
     for (int i = usage->fPlots.count()-1; i >= 0; --i) {
         GrPlot* plot = usage->fPlots[i];
-        if (plot->addSubImage(width, height, image, loc)) {
+        // client may have plots from more than one atlas, must check for ours before adding
+        if (this == plot->fAtlas && plot->addSubImage(width, height, image, loc)) {
             this->makeMRU(plot);
             return plot;
         }
index 9478d0436ceefc926672f8e6c7e62b50449118fe..7cfe91771f72e43ed97885ffc86ca45c0d7a6cc1 100755 (executable)
@@ -370,7 +370,7 @@ void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
             }
 
             // try to clear out an unused plot before we flush
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
                 fStrike->addGlyphToAtlas(glyph, scaler)) {
                 goto HAS_ATLAS;
             }
@@ -386,7 +386,7 @@ void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
             fContext->flush();
 
             // we should have an unused plot now
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
                 fStrike->addGlyphToAtlas(glyph, scaler)) {
                 goto HAS_ATLAS;
             }
@@ -422,6 +422,7 @@ HAS_ATLAS:
     width = SkIntToFixed(width);
     height = SkIntToFixed(height);
 
+    // the current texture/maskformat must match what the glyph needs
     GrTexture* texture = glyph->fPlot->texture();
     SkASSERT(texture);
 
@@ -429,9 +430,10 @@ HAS_ATLAS:
         this->flush();
         fCurrTexture = texture;
         fCurrTexture->ref();
+        fCurrMaskFormat = glyph->fMaskFormat;
     }
 
-    bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
+    bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat;
 
     if (NULL == fVertices) {
        // If we need to reserve vertices allow the draw target to suggest
@@ -549,12 +551,12 @@ void GrBitmapTextContext::flush() {
         // This effect could be stored with one of the cache objects (atlas?)
         drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
         SkASSERT(fStrike);
-        switch (fStrike->getMaskFormat()) {
+        switch (fCurrMaskFormat) {
                 // Color bitmap text
             case kARGB_GrMaskFormat:
                 SkASSERT(!drawState->hasColorVertexAttribute());
                 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-                drawState->setColor(0xffffffff);
+                drawState->setAlpha(fSkPaint.getAlpha());
                 break;
                 // LCD text
             case kA888_GrMaskFormat:
@@ -585,7 +587,7 @@ void GrBitmapTextContext::flush() {
                 SkASSERT(drawState->hasColorVertexAttribute());
                 break;
             default:
-                SkFAIL("Unexepected mask format.");
+                SkFAIL("Unexpected mask format.");
         }
         int nGlyphs = fCurrVertex / 4;
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
index 4bff399ade53632eb8603c93e6dc2e9b262e5570..a9805cb0fb0c2aa8e833b9c254bd38d6289d671c 100644 (file)
@@ -40,13 +40,14 @@ private:
 
     GrTextStrike*                     fStrike;
     void*                             fVertices;
-    int32_t                           fMaxVertices;
+    int                               fCurrVertex;
+    int                               fMaxVertices;
+    SkRect                            fVertexBounds;
     GrTexture*                        fCurrTexture;
+    GrMaskFormat                      fCurrMaskFormat;
     SkAutoTUnref<GrGeometryProcessor> fCachedGeometryProcessor;
     // Used to check whether fCachedEffect is still valid.
     uint32_t                          fEffectTextureUniqueID;
-    int                               fCurrVertex;
-    SkRect                            fVertexBounds;
 
     void init(const GrPaint&, const SkPaint&);
     void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
index baba10d570614ec2d106e12138ffd7a64242a9f2..a1f5ce66608bac5cdf9ab934faffde042257f25d 100755 (executable)
@@ -412,6 +412,11 @@ void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
         return;
     }
 
+    // TODO: support color glyphs
+    if (kA8_GrMaskFormat != glyph->fMaskFormat) {
+        return;
+    }
+
     SkScalar sx = SkFixedToScalar(vx);
     SkScalar sy = SkFixedToScalar(vy);
 /*
@@ -440,7 +445,7 @@ void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
             }
 
             // try to clear out an unused plot before we flush
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
                 fStrike->addGlyphToAtlas(glyph, scaler)) {
                 goto HAS_ATLAS;
             }
@@ -456,7 +461,7 @@ void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
             fContext->flush();
 
             // we should have an unused plot now
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
                 fStrike->addGlyphToAtlas(glyph, scaler)) {
                 goto HAS_ATLAS;
             }
index 164768f3b08bbfe29f67f226486bca99e1173e8e..b16b498ac1d31bce909c2d218c2d7f91141913c5 100644 (file)
@@ -59,7 +59,7 @@ GrFontScaler::~GrFontScaler() {
     SkSafeUnref(fKey);
 }
 
-GrMaskFormat GrFontScaler::getMaskFormat() {
+GrMaskFormat GrFontScaler::getMaskFormat() const {
     SkMask::Format format = fStrike->getMaskFormat();
     switch (format) {
         case SkMask::kBW_Format:
@@ -85,6 +85,28 @@ const GrFontDescKey* GrFontScaler::getKey() {
     return fKey;
 }
 
+GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(GrGlyph::PackedID packed) const {
+    const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
+                                                      GrGlyph::UnpackFixedX(packed),
+                                                      GrGlyph::UnpackFixedY(packed));
+    SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
+    switch (format) {
+        case SkMask::kBW_Format:
+            // fall through to kA8 -- we store BW glyphs in our 8-bit cache
+        case SkMask::kA8_Format:
+            return kA8_GrMaskFormat;
+        case SkMask::kLCD16_Format:
+            return kA565_GrMaskFormat;
+        case SkMask::kLCD32_Format:
+            return kA888_GrMaskFormat;
+        case SkMask::kARGB32_Format:
+            return kARGB_GrMaskFormat;
+        default:
+            SkDEBUGFAIL("unsupported SkMask::Format");
+            return kA8_GrMaskFormat;
+    }
+}
+
 bool GrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
                                                       GrGlyph::UnpackFixedX(packed),
index 8ae10cc8ddafc937230b61be62408e830914012c..81be3418f7ca1d8c71596bdbfb0afb55f16b602e 100644 (file)
@@ -80,20 +80,7 @@ static int mask_format_to_atlas_index(GrMaskFormat format) {
 }
 
 GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler) {
-    GrMaskFormat format = scaler->getMaskFormat();
-    GrPixelConfig config = mask_format_to_pixel_config(format);
-    int atlasIndex = mask_format_to_atlas_index(format);
-    if (NULL == fAtlases[atlasIndex]) {
-        SkISize textureSize = SkISize::Make(GR_ATLAS_TEXTURE_WIDTH,
-                                            GR_ATLAS_TEXTURE_HEIGHT);
-        fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrTextureFlags,
-                                                    textureSize,
-                                                    GR_NUM_PLOTS_X,
-                                                    GR_NUM_PLOTS_Y,
-                                                    true));
-    }
-    GrTextStrike* strike = SkNEW_ARGS(GrTextStrike,
-                                      (this, scaler->getKey(), format, fAtlases[atlasIndex]));
+    GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, (this, scaler->getKey()));
     fCache.add(strike);
 
     if (fHead) {
@@ -130,10 +117,30 @@ void GrFontCache::purgeStrike(GrTextStrike* strike) {
     delete strike;
 }
 
-bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) {
+
+GrPlot* GrFontCache::addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* usage,
+                                int width, int height, const void* image,
+                                SkIPoint16* loc) {
+    GrPixelConfig config = mask_format_to_pixel_config(format);
+    int atlasIndex = mask_format_to_atlas_index(format);
+    if (NULL == fAtlases[atlasIndex]) {
+        SkISize textureSize = SkISize::Make(GR_ATLAS_TEXTURE_WIDTH,
+                                            GR_ATLAS_TEXTURE_HEIGHT);
+        fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrTextureFlags,
+                                                    textureSize,
+                                                    GR_NUM_PLOTS_X,
+                                                    GR_NUM_PLOTS_Y,
+                                                    true));
+    }
+    return fAtlases[atlasIndex]->addToAtlas(usage, width, height, image, loc);
+}
+
+
+bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph) {
     SkASSERT(preserveStrike);
 
-    GrAtlas* atlas = preserveStrike->fAtlas;
+    int index = mask_format_to_atlas_index(glyph->fMaskFormat);
+    GrAtlas* atlas = fAtlases[index];
     GrPlot* plot = atlas->getUnusedPlot();
     if (NULL == plot) {
         return false;
@@ -141,13 +148,7 @@ bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) {
     plot->resetRects();
 
     GrTextStrike* strike = fHead;
-    GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
     while (strike) {
-        if (maskFormat != strike->fMaskFormat) {
-            strike = strike->fNext;
-            continue;
-        }
-
         GrTextStrike* strikeToPurge = strike;
         strike = strikeToPurge->fNext;
         strikeToPurge->removePlot(plot);
@@ -228,16 +229,11 @@ void GrFontCache::dump() const {
     atlas and a position within that texture.
  */
 
-GrTextStrike::GrTextStrike(GrFontCache* cache, const GrFontDescKey* key,
-                           GrMaskFormat format,
-                           GrAtlas* atlas) : fPool(64) {
+GrTextStrike::GrTextStrike(GrFontCache* cache, const GrFontDescKey* key) : fPool(64) {
     fFontScalerKey = key;
     fFontScalerKey->ref();
 
     fFontCache = cache;     // no need to ref, it won't go away before we do
-    fAtlas = atlas;         // no need to ref, it won't go away before we do
-
-    fMaskFormat = format;
 
 #ifdef SK_DEBUG
 //    GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
@@ -271,9 +267,10 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
             return NULL;
         }
     }
-
+    GrMaskFormat format = scaler->getPackedGlyphMaskFormat(packed);
+    
     GrGlyph* glyph = fPool.alloc();
-    glyph->init(packed, bounds);
+    glyph->init(packed, bounds, format);
     fCache.add(glyph);
     return glyph;
 }
@@ -317,7 +314,7 @@ bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
 
     SkAutoUnref ar(SkSafeRef(scaler));
 
-    int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
+    int bytesPerPixel = GrMaskFormatBytesPerPixel(glyph->fMaskFormat);
 
     size_t size = glyph->fBounds.area() * bytesPerPixel;
     GrAutoMalloc<1024> storage(size);
@@ -337,9 +334,9 @@ bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
         }
     }
 
-    GrPlot* plot  = fAtlas->addToAtlas(&fPlotUsage, glyph->width(),
-                                       glyph->height(), storage.get(),
-                                       &glyph->fAtlasLocation);
+    GrPlot* plot = fFontCache->addToAtlas(glyph->fMaskFormat, &fPlotUsage,
+                                          glyph->width(), glyph->height(),
+                                          storage.get(), &glyph->fAtlasLocation);
 
     if (NULL == plot) {
         return false;
index 401bd7325909aa39be8a2e0ee655e1a08cf3f3e9..779d676e433f2a50e3185898396db9c221c05ee6 100644 (file)
@@ -23,18 +23,16 @@ class GrGpu;
 class GrFontPurgeListener;
 
 /**
- *  The textcache maps a hostfontscaler instance to a dictionary of
+ *  The textstrike maps a hostfontscaler instance to a dictionary of
  *  glyphid->strike
  */
 class GrTextStrike {
 public:
-    GrTextStrike(GrFontCache*, const GrFontDescKey* fontScalerKey, GrMaskFormat, GrAtlas*);
+    GrTextStrike(GrFontCache*, const GrFontDescKey* fontScalerKey);
     ~GrTextStrike();
 
     const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
     GrFontCache* getFontCache() const { return fFontCache; }
-    GrMaskFormat getMaskFormat() const { return fMaskFormat; }
-    GrTexture*   getTexture() const { return fAtlas->getTexture(); }
 
     inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
     // returns true if glyph (or glyph+padding for distance field)
@@ -67,8 +65,6 @@ private:
     GrTAllocPool<GrGlyph> fPool;
 
     GrFontCache*    fFontCache;
-    GrAtlas*        fAtlas;
-    GrMaskFormat    fMaskFormat;
     bool            fUseDistanceField;
 
     GrAtlas::ClientPlotUsage fPlotUsage;
@@ -85,10 +81,15 @@ public:
 
     inline GrTextStrike* getStrike(GrFontScaler*, bool useDistanceField);
 
+    // add to texture atlas that matches this format
+    GrPlot* addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* usage,
+                       int width, int height, const void* image,
+                       SkIPoint16* loc);
+
     void freeAll();
 
-    // make an unused plot available
-    bool freeUnusedPlot(GrTextStrike* preserveStrike);
+    // make an unused plot available for this glyph
+    bool freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph);
 
     // testing
     int countStrikes() const { return fCache.count(); }