From 4f19ca325e8d0122e0a04345272d17e674460806 Mon Sep 17 00:00:00 2001 From: joshualitt Date: Thu, 30 Jul 2015 07:59:20 -0700 Subject: [PATCH] Dont try to draw glyphs with unexpected mask formats BUG=510931 Review URL: https://codereview.chromium.org/1269743003 --- src/gpu/GrAtlasTextContext.cpp | 6 ++++-- src/gpu/GrBatchFontCache.cpp | 10 ++++++---- src/gpu/GrBatchFontCache.h | 9 +++++++-- src/gpu/GrFontScaler.cpp | 14 +++++++++++++- src/gpu/GrFontScaler.h | 3 ++- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp index f3d6eafb2e..f5867ba9cb 100644 --- a/src/gpu/GrAtlasTextContext.cpp +++ b/src/gpu/GrAtlasTextContext.cpp @@ -1681,7 +1681,8 @@ public: glyph->fMaskFormat == this->maskFormat()); if (!fFontCache->hasGlyph(glyph) && - !strike->addGlyphToAtlas(batchTarget, glyph, scaler, skGlyph)) { + !strike->addGlyphToAtlas(batchTarget, glyph, scaler, skGlyph, + maskFormat)) { this->flush(batchTarget, &flushInfo); batchTarget->initDraw(gp, pipeline); brokenRun = glyphIdx > 0; @@ -1689,7 +1690,8 @@ public: SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(batchTarget, glyph, scaler, - skGlyph); + skGlyph, + maskFormat); SkASSERT(success); } fFontCache->addGlyphToBulkAndSetUseToken(&info.fBulkUseToken, glyph, diff --git a/src/gpu/GrBatchFontCache.cpp b/src/gpu/GrBatchFontCache.cpp index ecaa91e74d..dc5b43a547 100644 --- a/src/gpu/GrBatchFontCache.cpp +++ b/src/gpu/GrBatchFontCache.cpp @@ -196,7 +196,8 @@ void GrBatchTextStrike::removeID(GrBatchAtlas::AtlasID id) { } bool GrBatchTextStrike::addGlyphToAtlas(GrBatchTarget* batchTarget, GrGlyph* glyph, - GrFontScaler* scaler, const SkGlyph& skGlyph) { + GrFontScaler* scaler, const SkGlyph& skGlyph, + GrMaskFormat expectedMaskFormat) { SkASSERT(glyph); SkASSERT(scaler); SkASSERT(fCache.find(glyph->fPackedID)); @@ -204,7 +205,7 @@ bool GrBatchTextStrike::addGlyphToAtlas(GrBatchTarget* batchTarget, GrGlyph* gly SkAutoUnref ar(SkSafeRef(scaler)); - int bytesPerPixel = GrMaskFormatBytesPerPixel(glyph->fMaskFormat); + int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat); size_t size = glyph->fBounds.area() * bytesPerPixel; SkAutoSMalloc<1024> storage(size); @@ -216,12 +217,13 @@ bool GrBatchTextStrike::addGlyphToAtlas(GrBatchTarget* batchTarget, GrGlyph* gly } } else { if (!scaler->getPackedGlyphImage(skGlyph, glyph->width(), glyph->height(), - glyph->width() * bytesPerPixel, storage.get())) { + glyph->width() * bytesPerPixel, expectedMaskFormat, + storage.get())) { return false; } } - bool success = fBatchFontCache->addToAtlas(this, &glyph->fID, batchTarget, glyph->fMaskFormat, + bool success = fBatchFontCache->addToAtlas(this, &glyph->fID, batchTarget, expectedMaskFormat, glyph->width(), glyph->height(), storage.get(), &glyph->fAtlasLocation); if (success) { diff --git a/src/gpu/GrBatchFontCache.h b/src/gpu/GrBatchFontCache.h index 33f313c912..447fc3f991 100644 --- a/src/gpu/GrBatchFontCache.h +++ b/src/gpu/GrBatchFontCache.h @@ -40,8 +40,13 @@ public: return glyph; } - // returns true if glyph successfully added to texture atlas, false otherwise - bool addGlyphToAtlas(GrBatchTarget*, GrGlyph*, GrFontScaler*, const SkGlyph&); + // returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's + // mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never + // happen. + // TODO we can handle some of these cases if we really want to, but the long term solution is to + // get the actual glyph image itself when we get the glyph metrics. + bool addGlyphToAtlas(GrBatchTarget*, GrGlyph*, GrFontScaler*, const SkGlyph&, + GrMaskFormat expectedMaskFormat); // testing int countGlyphs() const { return fCache.count(); } diff --git a/src/gpu/GrFontScaler.cpp b/src/gpu/GrFontScaler.cpp index 84fd58133c..a9d5abff4e 100644 --- a/src/gpu/GrFontScaler.cpp +++ b/src/gpu/GrFontScaler.cpp @@ -103,7 +103,7 @@ void expand_bits(INT_TYPE* dst, } bool GrFontScaler::getPackedGlyphImage(const SkGlyph& glyph, int width, int height, int dstRB, - void* dst) { + GrMaskFormat expectedMaskFormat, void* dst) { SkASSERT(glyph.fWidth == width); SkASSERT(glyph.fHeight == height); const void* src = fStrike->findImage(glyph); @@ -111,6 +111,18 @@ bool GrFontScaler::getPackedGlyphImage(const SkGlyph& glyph, int width, int heig return false; } + // crbug:510931 + // Retrieving the image from the cache can actually change the mask format. This case is very + // uncommon so for now we just draw a clear box for these glyphs. + if (getPackedGlyphMaskFormat(glyph) != expectedMaskFormat) { + const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat); + for (int y = 0; y < height; y++) { + sk_bzero(dst, width * bpp); + dst = (char*)dst + dstRB; + } + return true; + } + int srcRB = glyph.rowBytes(); // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to // check the glyph's format, not the strike's format, and to be able to convert to any of the diff --git a/src/gpu/GrFontScaler.h b/src/gpu/GrFontScaler.h index 1dc5584c92..e42c7a1da0 100644 --- a/src/gpu/GrFontScaler.h +++ b/src/gpu/GrFontScaler.h @@ -52,7 +52,8 @@ public: GrMaskFormat getMaskFormat() const; GrMaskFormat getPackedGlyphMaskFormat(const SkGlyph&) const; bool getPackedGlyphBounds(const SkGlyph&, SkIRect* bounds); - bool getPackedGlyphImage(const SkGlyph&, int width, int height, int rowBytes, void* image); + bool getPackedGlyphImage(const SkGlyph&, int width, int height, int rowBytes, + GrMaskFormat expectedMaskFormat, void* image); bool getPackedGlyphDFBounds(const SkGlyph&, SkIRect* bounds); bool getPackedGlyphDFImage(const SkGlyph&, int width, int height, void* image); const SkPath* getGlyphPath(const SkGlyph&);