diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp index ce24fa0830..434a49f1dc 100644 --- a/src/core/SkGlyphRunPainter.cpp +++ b/src/core/SkGlyphRunPainter.cpp @@ -117,13 +117,6 @@ bool SkGlyphRunListPainter::ShouldDrawAsPath( return SkPaint::TooBigToUseCache(matrix, SkFontPriv::MakeTextMatrix(font), 1024); } -void SkGlyphRunListPainter::ensureBitmapBuffers(size_t runSize) { - if (runSize > fMaxRunSize) { - fPositions.reset(runSize); - fMaxRunSize = runSize; - } -} - static bool check_glyph_position(SkPoint position) { // Prevent glyphs from being drawn outside of or straddling the edge of device space. // Comparisons written a little weirdly so that NaN coordinates are treated safely. @@ -159,6 +152,8 @@ static SkMask create_mask(const SkGlyph& glyph, SkPoint position, const void* im void SkGlyphRunListPainter::drawForBitmapDevice( const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix, const BitmapDevicePainter* bitmapDevice) { + ScopedBuffers _ = this->ensureBuffers(glyphRunList); + const SkPaint& runPaint = glyphRunList.paint(); // The bitmap blitters can only draw lcd text to a N32 bitmap in srcOver. Otherwise, // convert the lcd text into A8 text. The props communicates this to the scaler. @@ -170,7 +165,6 @@ void SkGlyphRunListPainter::drawForBitmapDevice( for (auto& glyphRun : glyphRunList) { const SkFont& runFont = glyphRun.font(); auto runSize = glyphRun.runSize(); - this->ensureBitmapBuffers(runSize); if (ShouldDrawAsPath(runPaint, runFont, deviceMatrix)) { SkMatrix::MakeTrans(origin.x(), origin.y()).mapPoints( @@ -379,6 +373,7 @@ void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback( SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& deviceMatrix, PerEmptyT&& perEmpty, PerGlyphT&& perGlyph, PerPathT&& perPath) { + ScopedBuffers _ = this->ensureBuffers(glyphRun); SkMatrix mapping = deviceMatrix; mapping.preTranslate(origin.x(), origin.y()); @@ -386,7 +381,6 @@ void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback( mapping.postTranslate(rounding.x(), rounding.y()); auto runSize = glyphRun.runSize(); - this->ensureBitmapBuffers(runSize); mapping.mapPoints(fPositions, glyphRun.positions().data(), runSize); const SkPoint* mappedPtCursor = fPositions; for (auto glyphID : glyphRun.glyphsIDs()) { @@ -459,6 +453,20 @@ void SkGlyphRunListPainter::drawGlyphRunAsSDFWithARGBFallback( } } +SkGlyphRunListPainter::ScopedBuffers +SkGlyphRunListPainter::ensureBuffers(const SkGlyphRunList& glyphRunList) { + size_t size = 0; + for (const SkGlyphRun& run : glyphRunList) { + size = std::max(run.runSize(), size); + } + return ScopedBuffers(this, size); +} + +SkGlyphRunListPainter::ScopedBuffers +SkGlyphRunListPainter::ensureBuffers(const SkGlyphRun& glyphRun) { + return ScopedBuffers(this, glyphRun.runSize()); +} + #if SK_SUPPORT_GPU // -- GrTextContext -------------------------------------------------------------------------------- SkPMColor4f generate_filtered_color(const SkPaint& paint, const GrColorSpaceInfo& colorSpaceInfo) { @@ -1052,3 +1060,33 @@ bool SkTextBlobCacheDiffCanvas::TrackLayerDevice::maybeProcessGlyphRunForDFT( return true; } #endif + +SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* painter, int size) + : fPainter{painter} { + SkASSERT(size >= 0); + if (fPainter->fMaxRunSize < size) { + fPainter->fMaxRunSize = size; + + fPainter->fPositions.reset(size); + fPainter->fMaskGlyphs.reset(size); + fPainter->fMaskPositions.reset(size); + } +} + +SkGlyphRunListPainter::ScopedBuffers::~ScopedBuffers() { + fPainter->fPathGlyphs.clear(); + fPainter->fPathPositions.clear(); + fPainter->fARGBGlyphsIDs.clear(); + fPainter->fARGBPositions.clear(); + + if (200 < fPainter->fMaxRunSize) { + fPainter->fMaxRunSize = 0; + fPainter->fPositions.reset(); + fPainter->fMaskGlyphs.reset(); + fPainter->fMaskPositions.reset(); + fPainter->fPathGlyphs.shrink_to_fit(); + fPainter->fPathPositions.shrink_to_fit(); + fPainter->fARGBGlyphsIDs.shrink_to_fit(); + fPainter->fARGBPositions.shrink_to_fit(); + } +} diff --git a/src/core/SkGlyphRunPainter.h b/src/core/SkGlyphRunPainter.h index 7a464f8119..7d86e8c297 100644 --- a/src/core/SkGlyphRunPainter.h +++ b/src/core/SkGlyphRunPainter.h @@ -111,7 +111,16 @@ public: static bool ShouldDrawAsPath(const SkPaint& paint, const SkFont& font, const SkMatrix& matrix); private: - void ensureBitmapBuffers(size_t runSize); + struct ScopedBuffers { + ScopedBuffers(SkGlyphRunListPainter* painter, int size); + ~ScopedBuffers(); + SkGlyphRunListPainter* fPainter; + }; + + ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList); + + // TODO: Remove once I can hoist ensureBuffers above the list for loop in all cases. + ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun); void processARGBFallback( SkScalar maxGlyphDimension, const SkPaint& fallbackPaint, const SkFont& fallbackFont, @@ -123,8 +132,14 @@ private: const SkSurfaceProps fBitmapFallbackProps; const SkColorType fColorType; const SkScalerContextFlags fScalerContextFlags; - size_t fMaxRunSize{0}; + + int fMaxRunSize{0}; SkAutoTMalloc fPositions; + SkAutoTMalloc fMaskGlyphs; + SkAutoTMalloc fMaskPositions; + + std::vector fPathGlyphs; + std::vector fPathPositions; // Vectors for tracking ARGB fallback information. std::vector fARGBGlyphsIDs;