diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp index 480ef946e4..5c147eca3c 100644 --- a/src/core/SkGlyphRunPainter.cpp +++ b/src/core/SkGlyphRunPainter.cpp @@ -413,8 +413,6 @@ void GrTextContext::AppendGlyph(GrTextBlob* blob, int runIndex, } } -enum NeedsTransform : bool {kTransformDone = false, kDoTransform = true }; - // Getting glyphs to the screen in a fallback situation can be complex. Here is the set of // transformations that have to happen. Normally, they would all be accommodated by the font // scaler, but the atlas has an upper limit to the glyphs it can handle. So the GPU is used to @@ -437,49 +435,37 @@ enum NeedsTransform : bool {kTransformDone = false, kDoTransform = true }; // scale factor is used to increase the size of the destination rectangles. The destination // rectangles are then scaled, rotated, etc. by the GPU using the view matrix. -using ARGBFallback = - std::function fallbackGlyphIDs, // Colored glyphs that need to be handled - SkSpan fallbackPositions, // Positions of above glyphs - SkScalar fallbackTextScale, // Factor to go from text size to final size - const SkMatrix& glyphCacheMatrix, // Transformation performed by the glyph cache - NeedsTransform handleTransformLater)>; - -static void ARGB_fallback_helper( - SkSpan glyphIDs, - SkSpan positions, - SkScalar maxGlyphDimension, - const SkPaint& runPaint, - const SkMatrix& viewMatrix, - SkScalar pathScale, - ARGBFallback fallback) { - SkASSERT(!glyphIDs.empty()); +void SkGlyphRunListPainter::processARGBFallback( + SkScalar maxGlyphDimension, const SkPaint& runPaint, SkPoint origin, + const SkMatrix& viewMatrix, SkScalar textScale, ARGBFallback argbFallback) { + SkASSERT(!fARGBGlyphsIDs.empty()); SkScalar maxScale = viewMatrix.getMaxScale(); // This is a conservative estimate of the longest dimension among all the glyph widths and // heights. - SkScalar conservativeMaxGlyphDimension = maxGlyphDimension * pathScale * maxScale; + SkScalar conservativeMaxGlyphDimension = maxGlyphDimension * textScale * maxScale; // If the situation that the matrix is simple, and all the glyphs are small enough. Go fast! bool useFastPath = viewMatrix.isScaleTranslate() && conservativeMaxGlyphDimension <= maxGlyphDimension; + auto glyphIDs = SkSpan{fARGBGlyphsIDs}; + // A scaled and translated transform is the common case, and is handled directly in fallback. // Even if the transform is scale and translate, fallback must be careful to use glyphs that // fit in the atlas. If a glyph will not fit in the atlas, then the general transform case is // used to render the glyphs. if (useFastPath) { // Translate the positions to device space. - std::vector transformedPositions{positions.begin(), positions.end()}; - viewMatrix.mapPoints(transformedPositions.data(), transformedPositions.size()); - for (SkPoint& point : transformedPositions) { + viewMatrix.mapPoints(fARGBPositions.data(), fARGBPositions.size()); + for (SkPoint& point : fARGBPositions) { point.fX = SkScalarFloorToScalar(point.fX); point.fY = SkScalarFloorToScalar(point.fY); } - auto pos = SkSpan{transformedPositions}; - fallback(runPaint, glyphIDs, pos, SK_Scalar1, viewMatrix, kTransformDone); + auto positions = SkSpan{fARGBPositions}; + argbFallback(runPaint, glyphIDs, positions, SK_Scalar1, viewMatrix, kTransformDone); } else { // If the matrix is complicated or if scaling is used to fit the glyphs in the cache, @@ -508,13 +494,12 @@ static void ARGB_fallback_helper( SkPaint fallbackPaint{runPaint}; fallbackPaint.setTextSize(fallbackTextSize); SkScalar fallbackTextScale = runPaintTextSize / fallbackTextSize; - - fallback( - fallbackPaint, glyphIDs, positions, fallbackTextScale, SkMatrix::I(), kDoTransform); + auto positions = SkSpan{fARGBPositions}; + argbFallback( + fallbackPaint, glyphIDs, positions, fallbackTextScale, SkMatrix::I(), kDoTransform); } } - void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob, GrGlyphCache* glyphCache, const GrShaderCaps& shaderCaps, @@ -622,7 +607,8 @@ void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob, [blob{cacheBlob}, runIndex, props, scalerContextFlags, glyphCache, filteredColor] (const SkPaint& fallbackPaint, SkSpan glyphIDs, SkSpan positions, SkScalar textScale, - const SkMatrix& glyphCacheMatrix, NeedsTransform needsTransform) { + const SkMatrix& glyphCacheMatrix, + SkGlyphRunListPainter::NeedsTransform needsTransform) { blob->initOverride(runIndex); blob->setHasBitmap(); blob->setSubRunHasW(runIndex, glyphCacheMatrix.hasPerspective()); @@ -641,18 +627,8 @@ void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob, } }; - // Calculate paint, matrix, scale and positions for the fallback glyphs. - auto fallbackARGB = [&runPaint, &viewMatrix, textScale, argbFallback] - (SkSpan glyphIDs, - SkSpanpositions, - SkScalar maxGlyphDimension) { - - ARGB_fallback_helper(glyphIDs, positions, maxGlyphDimension, runPaint, - viewMatrix, textScale, argbFallback); - }; - glyphPainter->drawGlyphRunAsPathWithARGBFallback( - pathCache.get(), glyphRun, origin, perPath, fallbackARGB); + pathCache.get(), glyphRun, origin, viewMatrix, textScale, perPath, argbFallback); } else { // Ensure the blob is set for bitmaptext cacheBlob->setHasBitmap(); diff --git a/src/core/SkGlyphRunPainter.h b/src/core/SkGlyphRunPainter.h index 25f93c47bc..64f8444a41 100644 --- a/src/core/SkGlyphRunPainter.h +++ b/src/core/SkGlyphRunPainter.h @@ -46,16 +46,27 @@ public: SkPoint origin, const SkMatrix& deviceMatrix, PerGlyphT perGlyph, PerPathT perPath); + enum NeedsTransform : bool { kTransformDone = false, kDoTransform = true }; + + using ARGBFallback = + std::function fallbackGlyphIDs, // Colored glyphs + SkSpan fallbackPositions, // Positions of above glyphs + SkScalar fallbackTextScale, // Scale factor for glyph + const SkMatrix& glyphCacheMatrix, // Matrix of glyph cache + NeedsTransform handleTransformLater)>; // Positions / glyph transformed + // Draw glyphs as paths with fallback to scaled ARGB glyphs if color is needed. // PerPath - perPath(const SkGlyph&, SkPoint position) // FallbackARGB - fallbackARGB(SkSpan, SkSpan) // For each glyph that is not ARGB call perPath. If the glyph is ARGB then store the glyphID // and the position in fallback vectors. After all the glyphs are processed, pass the // fallback glyphIDs and positions to fallbackARGB. - template + template void drawGlyphRunAsPathWithARGBFallback( SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun, - SkPoint origin, PerPath perPath, FallbackARGB fallbackARGB); + SkPoint origin, const SkMatrix& viewMatrix, SkScalar textScale, + PerPath perPath, ARGBFallback fallbackARGB); template void drawGlyphRunAsSDFWithFallback( @@ -67,6 +78,9 @@ private: static bool ShouldDrawAsPath(const SkPaint& paint, const SkMatrix& matrix); bool ensureBitmapBuffers(size_t runSize); + void processARGBFallback( + SkScalar maxGlyphDimension, const SkPaint& runPaint, SkPoint origin, + const SkMatrix& viewMatrix, SkScalar textScale, ARGBFallback argbFallback); template void forEachMappedDrawableGlyph( @@ -91,6 +105,10 @@ private: const SkScalerContextFlags fScalerContextFlags; size_t fMaxRunSize{0}; SkAutoTMalloc fPositions; + + // Vectors for tracking ARGB fallback information. + std::vector fARGBGlyphsIDs; + std::vector fARGBPositions; }; inline static SkRect rect_to_draw( @@ -143,17 +161,17 @@ void SkGlyphRunListPainter::forEachMappedDrawableGlyph( } } -template +template void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback( SkGlyphCacheInterface* pathCache, const SkGlyphRun& glyphRun, - SkPoint origin, PerPathT perPath, FallbackARGB fallbackARGB) { - std::vector fallbackGlyphIDs; - std::vector fallbackPositions; + SkPoint origin, const SkMatrix& viewMatrix, SkScalar textScale, + PerPathT perPath, ARGBFallback argbFallback) { + fARGBGlyphsIDs.clear(); + fARGBPositions.clear(); SkScalar maxFallbackDimension{-SK_ScalarInfinity}; auto eachGlyph = - [pathCache, origin, perPath{std::move(perPath)}, - &fallbackGlyphIDs, &fallbackPositions, &maxFallbackDimension] + [this, pathCache, origin, perPath{std::move(perPath)}, &maxFallbackDimension] (SkGlyphID glyphID, SkPoint position) { if (SkScalarsAreFinite(position.x(), position.y())) { const SkGlyph& glyph = pathCache->getGlyphMetrics(glyphID, {0, 0}); @@ -163,8 +181,8 @@ void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback( } else { SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight); maxFallbackDimension = std::max(maxFallbackDimension, largestDimension); - fallbackGlyphIDs.push_back(glyphID); - fallbackPositions.push_back(position); + fARGBGlyphsIDs.push_back(glyphID); + fARGBPositions.push_back(position); } } } @@ -172,10 +190,10 @@ void SkGlyphRunListPainter::drawGlyphRunAsPathWithARGBFallback( glyphRun.forEachGlyphAndPosition(eachGlyph); - if (!fallbackGlyphIDs.empty()) { - fallbackARGB(SkSpan{fallbackGlyphIDs}, - SkSpan{fallbackPositions}, - maxFallbackDimension); + if (!fARGBGlyphsIDs.empty()) { + this->processARGBFallback( + maxFallbackDimension, glyphRun.paint(), origin, viewMatrix, textScale, argbFallback); + } }