Index: src/gpu/text/GrBatchFontCache.cpp |
diff --git a/src/gpu/text/GrBatchFontCache.cpp b/src/gpu/text/GrBatchFontCache.cpp |
index 06e199418ba92b326afca0fa637f5a21f5d12a2d..faafc16a13c022fabd80fee97b04064ca1617f52 100644 |
--- a/src/gpu/text/GrBatchFontCache.cpp |
+++ b/src/gpu/text/GrBatchFontCache.cpp |
@@ -15,8 +15,6 @@ |
#include "SkDistanceFieldGen.h" |
-/////////////////////////////////////////////////////////////////////////////// |
- |
bool GrBatchFontCache::initAtlas(GrMaskFormat format) { |
int index = MaskFormatToAtlasIndex(format); |
if (!fAtlases[index]) { |
@@ -145,6 +143,160 @@ void GrBatchFontCache::setAtlasSizes_ForTesting(const GrBatchAtlasConfig configs |
/////////////////////////////////////////////////////////////////////////////// |
+static inline GrMaskFormat get_packed_glyph_mask_format(const SkGlyph& glyph) { |
bsalomon
2016/05/17 19:11:04
This code is from GrFontScaler.cpp. Copied, pasted
|
+ 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::kARGB32_Format: |
+ return kARGB_GrMaskFormat; |
+ default: |
+ SkDEBUGFAIL("unsupported SkMask::Format"); |
+ return kA8_GrMaskFormat; |
+ } |
+} |
+ |
+static inline bool get_packed_glyph_bounds(SkGlyphCache* cache, const SkGlyph& glyph, |
+ SkIRect* bounds) { |
+#if 1 |
+ // crbug:510931 |
+ // Retrieving the image from the cache can actually change the mask format. |
+ cache->findImage(glyph); |
+#endif |
+ bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); |
+ |
+ return true; |
+} |
+ |
+static inline bool get_packed_glyph_df_bounds(SkGlyphCache* cache, const SkGlyph& glyph, |
+ SkIRect* bounds) { |
+#if 1 |
+ // crbug:510931 |
+ // Retrieving the image from the cache can actually change the mask format. |
+ cache->findImage(glyph); |
+#endif |
+ bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); |
+ bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad); |
+ |
+ return true; |
+} |
+ |
+// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to |
+// A8, RGB565, or RGBA8888. |
+template <typename INT_TYPE> |
+static void expand_bits(INT_TYPE* dst, |
+ const uint8_t* src, |
+ int width, |
+ int height, |
+ int dstRowBytes, |
+ int srcRowBytes) { |
+ for (int i = 0; i < height; ++i) { |
+ int rowWritesLeft = width; |
+ const uint8_t* s = src; |
+ INT_TYPE* d = dst; |
+ while (rowWritesLeft > 0) { |
+ unsigned mask = *s++; |
+ for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { |
+ *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0; |
+ } |
+ } |
+ dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes); |
+ src += srcRowBytes; |
+ } |
+} |
+ |
+static bool get_packed_glyph_image(SkGlyphCache* cache, const SkGlyph& glyph, int width, |
+ int height, int dstRB, GrMaskFormat expectedMaskFormat, |
+ void* dst) { |
+ SkASSERT(glyph.fWidth == width); |
+ SkASSERT(glyph.fHeight == height); |
+ const void* src = cache->findImage(glyph); |
+ if (nullptr == src) { |
+ 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 (get_packed_glyph_mask_format(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 |
+ // GrMaskFormats. |
+ if (SkMask::kBW_Format == glyph.fMaskFormat) { |
+ // expand bits to our mask type |
+ const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); |
+ switch (expectedMaskFormat) { |
+ case kA8_GrMaskFormat:{ |
+ uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); |
+ expand_bits(bytes, bits, width, height, dstRB, srcRB); |
+ break; |
+ } |
+ case kA565_GrMaskFormat: { |
+ uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst); |
+ expand_bits(rgb565, bits, width, height, dstRB, srcRB); |
+ break; |
+ } |
+ default: |
+ SkFAIL("Invalid GrMaskFormat"); |
+ } |
+ } else if (srcRB == dstRB) { |
+ memcpy(dst, src, dstRB * height); |
+ } else { |
+ const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat); |
+ for (int y = 0; y < height; y++) { |
+ memcpy(dst, src, width * bbp); |
+ src = (const char*)src + srcRB; |
+ dst = (char*)dst + dstRB; |
+ } |
+ } |
+ return true; |
+} |
+ |
+static bool get_packed_glyph_df_image(SkGlyphCache* cache, const SkGlyph& glyph, |
+ int width, int height, void* dst) { |
+ SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width); |
+ SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height); |
+ const void* image = cache->findImage(glyph); |
+ if (nullptr == image) { |
+ return false; |
+ } |
+ // now generate the distance field |
+ SkASSERT(dst); |
+ SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); |
+ if (SkMask::kA8_Format == maskFormat) { |
+ // make the distance field from the image |
+ SkGenerateDistanceFieldFromA8Image((unsigned char*)dst, |
+ (unsigned char*)image, |
+ glyph.fWidth, glyph.fHeight, |
+ glyph.rowBytes()); |
+ } else if (SkMask::kBW_Format == maskFormat) { |
+ // make the distance field from the image |
+ SkGenerateDistanceFieldFromBWImage((unsigned char*)dst, |
+ (unsigned char*)image, |
+ glyph.fWidth, glyph.fHeight, |
+ glyph.rowBytes()); |
+ } else { |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
/* |
The text strike is specific to a given font/style/matrix setup, which is |
represented by the GrHostFontScaler object we are given in getGlyph(). |
@@ -169,18 +321,18 @@ GrBatchTextStrike::~GrBatchTextStrike() { |
} |
GrGlyph* GrBatchTextStrike::generateGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed, |
- GrFontScaler* scaler) { |
+ SkGlyphCache* cache) { |
SkIRect bounds; |
if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(packed)) { |
- if (!scaler->getPackedGlyphDFBounds(skGlyph, &bounds)) { |
+ if (!get_packed_glyph_df_bounds(cache, skGlyph, &bounds)) { |
return nullptr; |
} |
} else { |
- if (!scaler->getPackedGlyphBounds(skGlyph, &bounds)) { |
+ if (!get_packed_glyph_bounds(cache, skGlyph, &bounds)) { |
return nullptr; |
} |
} |
- GrMaskFormat format = scaler->getPackedGlyphMaskFormat(skGlyph); |
+ GrMaskFormat format = get_packed_glyph_mask_format(skGlyph); |
GrGlyph* glyph = (GrGlyph*)fPool.alloc(sizeof(GrGlyph)); |
glyph->init(packed, bounds, format); |
@@ -202,10 +354,10 @@ void GrBatchTextStrike::removeID(GrBatchAtlas::AtlasID id) { |
bool GrBatchTextStrike::addGlyphToAtlas(GrDrawBatch::Target* target, |
GrGlyph* glyph, |
- GrFontScaler* scaler, |
+ SkGlyphCache* cache, |
GrMaskFormat expectedMaskFormat) { |
SkASSERT(glyph); |
- SkASSERT(scaler); |
+ SkASSERT(cache); |
SkASSERT(fCache.find(glyph->fPackedID)); |
int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat); |
@@ -213,16 +365,16 @@ bool GrBatchTextStrike::addGlyphToAtlas(GrDrawBatch::Target* target, |
size_t size = glyph->fBounds.area() * bytesPerPixel; |
SkAutoSMalloc<1024> storage(size); |
- const SkGlyph& skGlyph = scaler->grToSkGlyph(glyph->fPackedID); |
+ const SkGlyph& skGlyph = GrToSkGlyph(cache, glyph->fPackedID); |
if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID)) { |
- if (!scaler->getPackedGlyphDFImage(skGlyph, glyph->width(), glyph->height(), |
- storage.get())) { |
+ if (!get_packed_glyph_df_image(cache, skGlyph, glyph->width(), glyph->height(), |
+ storage.get())) { |
return false; |
} |
} else { |
- if (!scaler->getPackedGlyphImage(skGlyph, glyph->width(), glyph->height(), |
- glyph->width() * bytesPerPixel, expectedMaskFormat, |
- storage.get())) { |
+ if (!get_packed_glyph_image(cache, skGlyph, glyph->width(), glyph->height(), |
+ glyph->width() * bytesPerPixel, expectedMaskFormat, |
+ storage.get())) { |
return false; |
} |
} |