diff options
-rw-r--r-- | gyp/gpu.gypi | 2 | ||||
-rw-r--r-- | src/gpu/batches/GrAtlasTextBatch.cpp | 3 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.cpp | 9 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.h | 10 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp | 20 | ||||
-rw-r--r-- | src/gpu/text/GrBatchFontCache.cpp | 180 | ||||
-rw-r--r-- | src/gpu/text/GrBatchFontCache.h | 41 | ||||
-rw-r--r-- | src/gpu/text/GrFontScaler.cpp | 179 | ||||
-rw-r--r-- | src/gpu/text/GrFontScaler.h | 47 | ||||
-rw-r--r-- | src/gpu/text/GrTextUtils.cpp | 50 | ||||
-rw-r--r-- | src/gpu/text/GrTextUtils.h | 6 |
11 files changed, 221 insertions, 326 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index dc16c2cab2..5c55aec33f 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -316,8 +316,6 @@ '<(skia_src_path)/gpu/text/GrBatchFontCache.h', '<(skia_src_path)/gpu/text/GrDistanceFieldAdjustTable.cpp', '<(skia_src_path)/gpu/text/GrDistanceFieldAdjustTable.h', - '<(skia_src_path)/gpu/text/GrFontScaler.cpp', - '<(skia_src_path)/gpu/text/GrFontScaler.h', '<(skia_src_path)/gpu/text/GrStencilAndCoverTextContext.cpp', '<(skia_src_path)/gpu/text/GrStencilAndCoverTextContext.h', '<(skia_src_path)/gpu/text/GrTextBlobCache.cpp', diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp index bdf69861a4..2da4938e79 100644 --- a/src/gpu/batches/GrAtlasTextBatch.cpp +++ b/src/gpu/batches/GrAtlasTextBatch.cpp @@ -136,7 +136,6 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { // in a row const SkDescriptor* desc = nullptr; SkGlyphCache* cache = nullptr; - GrFontScaler* scaler = nullptr; SkTypeface* typeface = nullptr; GrBlobRegenHelper helper(this, target, &flushInfo); @@ -148,7 +147,7 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { void* blobVertices; int subRunGlyphCount; blob->regenInBatch(target, fFontCache, &helper, args.fRun, args.fSubRun, &cache, - &typeface, &scaler, &desc, vertexStride, args.fViewMatrix, args.fX, + &typeface, &desc, vertexStride, args.fViewMatrix, args.fX, args.fY, args.fColor, &blobVertices, &byteCount, &subRunGlyphCount); // now copy all vertices diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp index 03260a6e52..54af7af87a 100644 --- a/src/gpu/text/GrAtlasTextBlob.cpp +++ b/src/gpu/text/GrAtlasTextBlob.cpp @@ -48,7 +48,6 @@ GrAtlasTextBlob* GrAtlasTextBlob::Create(GrMemoryPool* pool, int glyphCount, int return cacheBlob; } - SkGlyphCache* GrAtlasTextBlob::setupCache(int runIndex, const SkSurfaceProps& props, uint32_t scalerContextFlags, @@ -69,12 +68,12 @@ void GrAtlasTextBlob::appendGlyph(int runIndex, GrColor color, GrBatchTextStrike* strike, GrGlyph* glyph, - GrFontScaler* scaler, const SkGlyph& skGlyph, + SkGlyphCache* cache, const SkGlyph& skGlyph, SkScalar x, SkScalar y, SkScalar scale, bool applyVM) { // If the glyph is too large we fall back to paths if (glyph->fTooLargeForAtlas) { - this->appendLargeGlyph(glyph, scaler, skGlyph, x, y, scale, applyVM); + this->appendLargeGlyph(glyph, cache, skGlyph, x, y, scale, applyVM); return; } @@ -152,10 +151,10 @@ void GrAtlasTextBlob::appendGlyph(int runIndex, subRun->glyphAppended(); } -void GrAtlasTextBlob::appendLargeGlyph(GrGlyph* glyph, GrFontScaler* scaler, const SkGlyph& skGlyph, +void GrAtlasTextBlob::appendLargeGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph, SkScalar x, SkScalar y, SkScalar scale, bool applyVM) { if (nullptr == glyph->fPath) { - const SkPath* glyphPath = scaler->getGlyphPath(skGlyph); + const SkPath* glyphPath = cache->findPath(skGlyph); if (!glyphPath) { return; } diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h index e0e9bb8bdf..788eaba77b 100644 --- a/src/gpu/text/GrAtlasTextBlob.h +++ b/src/gpu/text/GrAtlasTextBlob.h @@ -160,7 +160,7 @@ public: GrColor color, GrBatchTextStrike* strike, GrGlyph* glyph, - GrFontScaler* scaler, const SkGlyph& skGlyph, + SkGlyphCache*, const SkGlyph& skGlyph, SkScalar x, SkScalar y, SkScalar scale, bool applyVM); static size_t GetVertexStride(GrMaskFormat maskFormat) { @@ -258,8 +258,7 @@ public: void regenInBatch(GrDrawBatch::Target* target, GrBatchFontCache* fontCache, GrBlobRegenHelper *helper, int run, int subRun, SkGlyphCache** cache, - SkTypeface** typeface, GrFontScaler** scaler, - const SkDescriptor** desc, size_t vertexStride, + SkTypeface** typeface, const SkDescriptor** desc, size_t vertexStride, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, void** vertices, size_t* byteCount, int* glyphCount); @@ -286,7 +285,7 @@ private: , fMinMaxScale(SK_ScalarMax) , fTextType(0) {} - void appendLargeGlyph(GrGlyph* glyph, GrFontScaler* scaler, const SkGlyph& skGlyph, + void appendLargeGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph, SkScalar x, SkScalar y, SkScalar scale, bool applyVM); inline void flushRun(GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder, const GrClip&, @@ -491,8 +490,7 @@ private: GrBatchFontCache* fontCache, GrBlobRegenHelper* helper, Run* run, Run::SubRunInfo* info, SkGlyphCache** cache, - SkTypeface** typeface, GrFontScaler** scaler, - const SkDescriptor** desc, + SkTypeface** typeface, const SkDescriptor** desc, int glyphCount, size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const; diff --git a/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp b/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp index 94bfb1b953..e5a8956517 100644 --- a/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp +++ b/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp @@ -143,7 +143,7 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, GrBlobRegenHelper *helper, Run* run, Run::SubRunInfo* info, SkGlyphCache** cache, - SkTypeface** typeface, GrFontScaler** scaler, + SkTypeface** typeface, const SkDescriptor** desc, int glyphCount, size_t vertexStride, GrColor color, SkScalar transX, @@ -166,12 +166,11 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, } *desc = newDesc; *cache = SkGlyphCache::DetachCache(run->fTypeface, run->fEffects, *desc); - *scaler = GrTextUtils::GetGrFontScaler(*cache); *typeface = run->fTypeface; } if (regenGlyphs) { - strike = fontCache->getStrike(*scaler); + strike = fontCache->getStrike(*cache); } else { strike = info->strike(); } @@ -188,20 +187,20 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, // Get the id from the old glyph, and use the new strike to lookup // the glyph. GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID; - fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(), *scaler); + fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(), *cache); SkASSERT(id == fGlyphs[glyphOffset]->fPackedID); } glyph = fGlyphs[glyphOffset]; SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat()); if (!fontCache->hasGlyph(glyph) && - !strike->addGlyphToAtlas(target, glyph, *scaler, info->maskFormat())) { + !strike->addGlyphToAtlas(target, glyph, *cache, info->maskFormat())) { helper->flush(); brokenRun = glyphIdx > 0; SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, glyph, - *scaler, + *cache, info->maskFormat()); SkASSERT(success); } @@ -248,17 +247,16 @@ enum RegenMask { kRegenColTexGlyph = kRegenCol | kRegenGlyph, }; -#define REGEN_ARGS target, fontCache, helper, &run, &info, cache, typeface, scaler, desc, \ +#define REGEN_ARGS target, fontCache, helper, &run, &info, cache, typeface, desc, \ *glyphCount, vertexStride, color, transX, transY void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, GrBatchFontCache* fontCache, GrBlobRegenHelper *helper, int runIndex, int subRunIndex, SkGlyphCache** cache, - SkTypeface** typeface, GrFontScaler** scaler, - const SkDescriptor** desc, size_t vertexStride, - const SkMatrix& viewMatrix, SkScalar x, SkScalar y, - GrColor color, + SkTypeface** typeface, const SkDescriptor** desc, + size_t vertexStride, const SkMatrix& viewMatrix, + SkScalar x, SkScalar y, GrColor color, void** vertices, size_t* byteCount, int* glyphCount) { Run& run = fRuns[runIndex]; Run::SubRunInfo& info = run.fSubRunInfo[subRunIndex]; diff --git a/src/gpu/text/GrBatchFontCache.cpp b/src/gpu/text/GrBatchFontCache.cpp index 06e199418b..faafc16a13 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) { + 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; } } diff --git a/src/gpu/text/GrBatchFontCache.h b/src/gpu/text/GrBatchFontCache.h index 4429885193..42612fe8b6 100644 --- a/src/gpu/text/GrBatchFontCache.h +++ b/src/gpu/text/GrBatchFontCache.h @@ -9,9 +9,8 @@ #define GrBatchFontCache_DEFINED #include "GrBatchAtlas.h" -#include "GrFontScaler.h" #include "GrGlyph.h" -#include "SkGlyph.h" +#include "SkGlyphCache.h" #include "SkTDynamicHash.h" #include "SkVarAlloc.h" @@ -20,9 +19,9 @@ class GrGpu; /** * The GrBatchTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory - * is indexed by a PackedID and GrFontScaler. The GrFontScaler is what actually creates the mask. - * The GrBatchTextStrike may outlive the generating GrFontScaler. However, it retains a copy - * of it's SkDescriptor as a key to access (or regenerate) the GrFontScaler. GrBatchTextStrikes are + * is indexed by a PackedID and SkGlyphCache. The SkGlyphCache is what actually creates the mask. + * The GrBatchTextStrike may outlive the generating SkGlyphCache. However, it retains a copy + * of it's SkDescriptor as a key to access (or regenerate) the SkGlyphCache. GrBatchTextStrikes are * created by and owned by a GrBatchFontCache. */ class GrBatchTextStrike : public SkNVRefCnt<GrBatchTextStrike> { @@ -32,10 +31,10 @@ public: ~GrBatchTextStrike(); inline GrGlyph* getGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed, - GrFontScaler* scaler) { + SkGlyphCache* cache) { GrGlyph* glyph = fCache.find(packed); if (nullptr == glyph) { - glyph = this->generateGlyph(skGlyph, packed, scaler); + glyph = this->generateGlyph(skGlyph, packed, cache); } return glyph; } @@ -46,14 +45,14 @@ public: // skbug:4143 crbug:510931 inline GrGlyph* getGlyph(GrGlyph::PackedID packed, GrMaskFormat expectedMaskFormat, - GrFontScaler* scaler) { + SkGlyphCache* cache) { GrGlyph* glyph = fCache.find(packed); if (nullptr == glyph) { // We could return this to the caller, but in practice it adds code complexity for // potentially little benefit(ie, if the glyph is not in our font cache, then its not // in the atlas and we're going to be doing a texture upload anyways). - const SkGlyph& skGlyph = scaler->grToSkGlyph(packed); - glyph = this->generateGlyph(skGlyph, packed, scaler); + const SkGlyph& skGlyph = GrToSkGlyph(cache, packed); + glyph = this->generateGlyph(skGlyph, packed, cache); glyph->fMaskFormat = expectedMaskFormat; } return glyph; @@ -64,7 +63,7 @@ public: // 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(GrDrawBatch::Target*, GrGlyph*, GrFontScaler*, + bool addGlyphToAtlas(GrDrawBatch::Target*, GrGlyph*, SkGlyphCache*, GrMaskFormat expectedMaskFormat); // testing @@ -91,13 +90,19 @@ private: int fAtlasedGlyphs; bool fIsAbandoned; - GrGlyph* generateGlyph(const SkGlyph&, GrGlyph::PackedID, GrFontScaler*); + static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, GrGlyph::PackedID id) { + return cache->getGlyphIDMetrics(GrGlyph::UnpackID(id), + GrGlyph::UnpackFixedX(id), + GrGlyph::UnpackFixedY(id)); + } + + GrGlyph* generateGlyph(const SkGlyph&, GrGlyph::PackedID, SkGlyphCache*); friend class GrBatchFontCache; }; /* - * GrBatchFontCache manages strikes which are indexed by a GrFontScaler. These strikes can then be + * GrBatchFontCache manages strikes which are indexed by a SkGlyphCache. These strikes can then be * used to individual Glyph Masks. The GrBatchFontCache also manages GrBatchAtlases, though this is * more or less transparent to the client(aside from atlasGeneration, described below). * Note - we used to initialize the backing atlas for the GrBatchFontCache at initialization time. @@ -112,10 +117,10 @@ public: // another client of the cache may cause the strike to be purged while it is still reffed. // Therefore, the caller must check GrBatchTextStrike::isAbandoned() if there are other // interactions with the cache since the strike was received. - inline GrBatchTextStrike* getStrike(GrFontScaler* scaler) { - GrBatchTextStrike* strike = fCache.find(scaler->getKey()); + inline GrBatchTextStrike* getStrike(const SkGlyphCache* cache) { + GrBatchTextStrike* strike = fCache.find(cache->getDescriptor()); if (nullptr == strike) { - strike = this->generateStrike(scaler); + strike = this->generateStrike(cache); } return strike; } @@ -207,8 +212,8 @@ private: bool initAtlas(GrMaskFormat); - GrBatchTextStrike* generateStrike(GrFontScaler* scaler) { - GrBatchTextStrike* strike = new GrBatchTextStrike(this, scaler->getKey()); + GrBatchTextStrike* generateStrike(const SkGlyphCache* cache) { + GrBatchTextStrike* strike = new GrBatchTextStrike(this, cache->getDescriptor()); fCache.add(strike); return strike; } diff --git a/src/gpu/text/GrFontScaler.cpp b/src/gpu/text/GrFontScaler.cpp deleted file mode 100644 index 796f4d46c0..0000000000 --- a/src/gpu/text/GrFontScaler.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrFontScaler.h" -#include "SkDescriptor.h" -#include "SkDistanceFieldGen.h" -#include "SkGlyphCache.h" - -/////////////////////////////////////////////////////////////////////////////// - -GrFontScaler::GrFontScaler(SkGlyphCache* strike) { - fStrike = strike; -} - -const SkDescriptor& GrFontScaler::getKey() { return fStrike->getDescriptor(); } - -GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(const SkGlyph& glyph) const { - 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; - } -} - -bool GrFontScaler::getPackedGlyphBounds(const SkGlyph& glyph, SkIRect* bounds) { -#if 1 - // crbug:510931 - // Retrieving the image from the cache can actually change the mask format. - fStrike->findImage(glyph); -#endif - bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); - - return true; -} - -bool GrFontScaler::getPackedGlyphDFBounds(const SkGlyph& glyph, SkIRect* bounds) { -#if 1 - // crbug:510931 - // Retrieving the image from the cache can actually change the mask format. - fStrike->findImage(glyph); -#endif - bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); - bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad); - - return true; -} - -namespace { -// 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> -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; - } -} -} - -bool GrFontScaler::getPackedGlyphImage(const SkGlyph& glyph, int width, int height, int dstRB, - GrMaskFormat expectedMaskFormat, void* dst) { - SkASSERT(glyph.fWidth == width); - SkASSERT(glyph.fHeight == height); - const void* src = fStrike->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 (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 - // 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; -} - -bool GrFontScaler::getPackedGlyphDFImage(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 = fStrike->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; -} - -const SkPath* GrFontScaler::getGlyphPath(const SkGlyph& glyph) { - return fStrike->findPath(glyph); -} - -const SkGlyph& GrFontScaler::grToSkGlyph(GrGlyph::PackedID id) { - return fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(id), - GrGlyph::UnpackFixedX(id), - GrGlyph::UnpackFixedY(id)); -} diff --git a/src/gpu/text/GrFontScaler.h b/src/gpu/text/GrFontScaler.h deleted file mode 100644 index 41cce99fa5..0000000000 --- a/src/gpu/text/GrFontScaler.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrFontScaler_DEFINED -#define GrFontScaler_DEFINED - -#include "GrGlyph.h" -#include "GrTypes.h" - -#include "SkDescriptor.h" - -class SkGlyph; -class SkPath; - -/* - * This is Gr's interface to the host platform's font scaler. - * - * The client is responsible for instantiating this. The instance is created - * for a specific font+size+matrix. - */ -class GrFontScaler final : public SkNoncopyable { -public: - explicit GrFontScaler(SkGlyphCache* strike); - - const SkDescriptor& getKey(); - GrMaskFormat getPackedGlyphMaskFormat(const SkGlyph&) const; - bool getPackedGlyphBounds(const SkGlyph&, SkIRect* bounds); - 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&); - const SkGlyph& grToSkGlyph(GrGlyph::PackedID); - -private: - // The SkGlyphCache actually owns this GrFontScaler. The GrFontScaler is deleted when the - // SkGlyphCache is deleted. - SkGlyphCache* fStrike; - - typedef SkNoncopyable INHERITED; -}; - -#endif diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp index da2b3e20db..9205d2fd7c 100644 --- a/src/gpu/text/GrTextUtils.cpp +++ b/src/gpu/text/GrTextUtils.cpp @@ -56,11 +56,8 @@ void GrTextUtils::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, GrBatchTextStrike* currStrike = nullptr; - // Get GrFontScaler from cache SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, skPaint, &viewMatrix); - GrFontScaler* fontScaler = GrTextUtils::GetGrFontScaler(cache); - SkFindAndPlaceGlyph::ProcessText( skPaint.getTextEncoding(), text, byteLength, {x, y}, viewMatrix, skPaint.getTextAlign(), @@ -70,7 +67,7 @@ void GrTextUtils::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, BmpAppendGlyph( blob, runIndex, fontCache, &currStrike, glyph, SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY), - color, fontScaler); + color, cache); } ); @@ -98,10 +95,8 @@ void GrTextUtils::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, GrBatchTextStrike* currStrike = nullptr; - // Get GrFontScaler from cache SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, skPaint, &viewMatrix); - GrFontScaler* fontScaler = GrTextUtils::GetGrFontScaler(cache); SkFindAndPlaceGlyph::ProcessPosText( skPaint.getTextEncoding(), text, byteLength, @@ -112,7 +107,7 @@ void GrTextUtils::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, BmpAppendGlyph( blob, runIndex, fontCache, &currStrike, glyph, SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY), - color, fontScaler); + color, cache); } ); @@ -122,16 +117,16 @@ void GrTextUtils::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, void GrTextUtils::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, GrBatchFontCache* fontCache, GrBatchTextStrike** strike, const SkGlyph& skGlyph, - int vx, int vy, GrColor color, GrFontScaler* scaler) { + int vx, int vy, GrColor color, SkGlyphCache* cache) { if (!*strike) { - *strike = fontCache->getStrike(scaler); + *strike = fontCache->getStrike(cache); } GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), skGlyph.getSubXFixed(), skGlyph.getSubYFixed(), GrGlyph::kCoverage_MaskStyle); - GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, scaler); + GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, cache); if (!glyph) { return; } @@ -149,7 +144,7 @@ void GrTextUtils::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, r.fRight = r.fLeft + SkIntToScalar(width); r.fBottom = r.fTop + SkIntToScalar(height); - blob->appendGlyph(runIndex, r, color, *strike, glyph, scaler, skGlyph, + blob->appendGlyph(runIndex, r, color, *strike, glyph, cache, skGlyph, SkIntToScalar(vx), SkIntToScalar(vy), 1.0f, false); } @@ -351,7 +346,6 @@ void GrTextUtils::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, SkGlyphCache* cache = blob->setupCache(runIndex, props, SkPaint::kNone_ScalerContextFlags, dfPaint, nullptr); SkPaint::GlyphCacheProc glyphCacheProc = dfPaint.getGlyphCacheProc(true); - GrFontScaler* fontScaler = GrTextUtils::GetGrFontScaler(cache); const char* stop = text + byteLength; @@ -370,7 +364,7 @@ void GrTextUtils::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, fontCache, &currStrike, glyph, - x, y, color, fontScaler, + x, y, color, cache, textRatio, viewMatrix)) { // couldn't append, send to fallback fallbackTxt.append(SkToInt(text-lastText), lastText); @@ -403,7 +397,7 @@ void GrTextUtils::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, &currStrike, glyph, x - advanceX, y - advanceY, color, - fontScaler, + cache, textRatio, viewMatrix)) { // couldn't append, send to fallback @@ -431,17 +425,17 @@ void GrTextUtils::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, bool GrTextUtils::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, GrBatchFontCache* cache, GrBatchTextStrike** strike, const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, GrColor color, - GrFontScaler* scaler, + SkGlyphCache* glyphCache, SkScalar textRatio, const SkMatrix& viewMatrix) { if (!*strike) { - *strike = cache->getStrike(scaler); + *strike = cache->getStrike(glyphCache); } GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), skGlyph.getSubXFixed(), skGlyph.getSubYFixed(), GrGlyph::kDistance_MaskStyle); - GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, scaler); + GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache); if (!glyph) { return true; } @@ -465,7 +459,7 @@ bool GrTextUtils::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, GrBatchFont sy += dy; SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); - blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, scaler, skGlyph, + blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, sx - dx, sy - dy, scale, true); return true; } @@ -569,23 +563,3 @@ uint32_t GrTextUtils::FilterTextFlags(const SkSurfaceProps& surfaceProps, const return flags; } - -static void glyph_cache_aux_proc(void* data) { - GrFontScaler* scaler = (GrFontScaler*)data; - delete scaler; -} - -GrFontScaler* GrTextUtils::GetGrFontScaler(SkGlyphCache* cache) { - void* auxData; - GrFontScaler* scaler = nullptr; - - if (cache->getAuxProcData(glyph_cache_aux_proc, &auxData)) { - scaler = (GrFontScaler*)auxData; - } - if (nullptr == scaler) { - scaler = new GrFontScaler(cache); - cache->setAuxProc(glyph_cache_aux_proc, scaler); - } - - return scaler; -} diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h index 7823473f77..c218ab7da1 100644 --- a/src/gpu/text/GrTextUtils.h +++ b/src/gpu/text/GrTextUtils.h @@ -18,7 +18,6 @@ class GrBatchTextStrike; class GrClip; class GrContext; class GrDrawContext; -class GrFontScaler; class GrShaderCaps; class SkGlyph; class SkMatrix; @@ -85,7 +84,6 @@ public: static bool ShouldDisableLCD(const SkPaint& paint); - static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache); static uint32_t FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint); private: @@ -96,12 +94,12 @@ private: static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrBatchFontCache*, GrBatchTextStrike**, const SkGlyph&, int left, int top, - GrColor color, GrFontScaler*); + GrColor color, SkGlyphCache*); static bool DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrBatchFontCache*, GrBatchTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy, GrColor color, - GrFontScaler* scaler, + SkGlyphCache* cache, SkScalar textRatio, const SkMatrix& viewMatrix); }; |