diff options
author | 2018-02-06 11:14:20 -0500 | |
---|---|---|
committer | 2018-02-06 17:28:16 +0000 | |
commit | 2fb7c8aef57e4b94d5215e618d8c3b4cccd35edf (patch) | |
tree | f9d56b011d402a858e3c69717605f6f78cb2693e /src/gpu/text/GrAtlasTextContext.cpp | |
parent | e1ddce57ea78ed1ec1a7297cb9799b5a64aaa937 (diff) |
Cleanup of large text rendering.
* Switch all path glyphs to be rendered as part of the fBigGlyphs
(now fPathGlyphs) system
* Use one flush command for both cached and throwaway blobs
* Store and render path glyphs per run rather than one list for the
entire blob (fixes a layering bug)
* Fix bug with scaled fallback glyphs, where fallback glyphs were
trying to use more than one descriptor
Bug: skia:7562
Change-Id: Ic3d01887e2203a844102a04afe8674a16149b4bb
Reviewed-on: https://skia-review.googlesource.com/102400
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Diffstat (limited to 'src/gpu/text/GrAtlasTextContext.cpp')
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.cpp | 229 |
1 files changed, 149 insertions, 80 deletions
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp index 1dce4e0d44..3155153289 100644 --- a/src/gpu/text/GrAtlasTextContext.cpp +++ b/src/gpu/text/GrAtlasTextContext.cpp @@ -11,11 +11,15 @@ #include "SkDistanceFieldGen.h" #include "SkDraw.h" #include "SkDrawFilter.h" +#include "SkDrawProcs.h" #include "SkFindAndPlaceGlyph.h" #include "SkGr.h" #include "SkGraphics.h" #include "SkMakeUnique.h" #include "SkMaskFilterBase.h" +#include "SkTextMapStateProc.h" +#include "SkTextToPathIter.h" + #include "ops/GrMeshDrawOp.h" // DF sizes and thresholds for usage of the small and medium sizes. For example, above @@ -49,15 +53,6 @@ std::unique_ptr<GrAtlasTextContext> GrAtlasTextContext::Make(const Options& opti return std::unique_ptr<GrAtlasTextContext>(new GrAtlasTextContext(options)); } -bool GrAtlasTextContext::canDraw(const GrAtlasGlyphCache* fontCache, - const SkPaint& skPaint, - const SkMatrix& viewMatrix, - const SkSurfaceProps& props, - const GrShaderCaps& shaderCaps) { - return this->canDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps) || - !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix, fontCache->getGlyphSizeLimit()); -} - SkColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) { SkColor canonicalColor = paint.computeLuminanceColor(); if (lcd) { @@ -186,8 +181,8 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t viewMatrix, props, blob, x, y, drawFilter); } - cacheBlob->flushCached(atlasGlyphCache, target, blob, props, fDistanceAdjustTable.get(), paint, - drawFilter, clip, viewMatrix, clipBounds, x, y); + cacheBlob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, + clip, viewMatrix, clipBounds, x, y); } void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, @@ -235,8 +230,6 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, break; } } - } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { - cacheBlob->setRunTooBigForAtlas(run); } else { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: @@ -328,23 +321,15 @@ void GrAtlasTextContext::drawText(GrContext* context, GrTextUtils::Target* targe auto textBlobCache = context->contextPriv().getTextBlobCache(); GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); - if (this->canDraw(atlasGlyphCache, skPaint, viewMatrix, props, - *context->caps()->shaderCaps())) { - sk_sp<GrAtlasTextBlob> blob( - this->makeDrawTextBlob(textBlobCache, atlasGlyphCache, - *context->caps()->shaderCaps(), paint, - ComputeScalerContextFlags(target->colorSpaceInfo()), - viewMatrix, props, text, byteLength, x, y)); - if (blob) { - blob->flushThrowaway(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, - clip, viewMatrix, regionClipBounds, x, y); - } - return; + sk_sp<GrAtlasTextBlob> blob( + this->makeDrawTextBlob(textBlobCache, atlasGlyphCache, + *context->caps()->shaderCaps(), paint, + ComputeScalerContextFlags(target->colorSpaceInfo()), + viewMatrix, props, text, byteLength, x, y)); + if (blob) { + blob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, + clip, viewMatrix, regionClipBounds, x, y); } - - // fall back to drawing as a path or scaled glyph - GrTextUtils::DrawBigText(target, clip, paint, viewMatrix, text, byteLength, x, y, - regionClipBounds); } void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target, @@ -361,23 +346,15 @@ void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* ta auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache(); auto textBlobCache = context->contextPriv().getTextBlobCache(); - if (this->canDraw(atlasGlyphCache, skPaint, viewMatrix, props, - *context->caps()->shaderCaps())) { - sk_sp<GrAtlasTextBlob> blob(this->makeDrawPosTextBlob( - textBlobCache, atlasGlyphCache, - *context->caps()->shaderCaps(), paint, - ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text, - byteLength, pos, scalarsPerPosition, offset)); - if (blob) { - blob->flushThrowaway(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, - clip, viewMatrix, regionClipBounds, offset.fX, offset.fY); - } - return; + sk_sp<GrAtlasTextBlob> blob(this->makeDrawPosTextBlob( + textBlobCache, atlasGlyphCache, + *context->caps()->shaderCaps(), paint, + ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text, + byteLength, pos, scalarsPerPosition, offset)); + if (blob) { + blob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, + clip, viewMatrix, regionClipBounds, offset.fX, offset.fY); } - - // fall back to drawing as a path or scaled glyph - GrTextUtils::DrawBigPosText(target, props, clip, paint, viewMatrix, text, - byteLength, pos, scalarsPerPosition, offset, regionClipBounds); } void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, @@ -396,8 +373,11 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, // Ensure the blob is set for bitmaptext blob->setHasBitmap(); + if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { + DrawBmpTextAsPaths(blob, runIndex, paint, text, byteLength, x, y); + return; + } GrAtlasTextStrike* currStrike = nullptr; - SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); SkFindAndPlaceGlyph::ProcessText(paint.skPaint().getTextEncoding(), text, byteLength, {x, y}, viewMatrix, paint.skPaint().getTextAlign(), cache, @@ -432,10 +412,15 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, // Ensure the blob is set for bitmaptext blob->setHasBitmap(); + if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { + DrawBmpPosTextAsPaths(blob, runIndex, props, paint, text, byteLength, + pos, scalarsPerPosition, offset, textRatio); + return; + } + GrAtlasTextStrike* currStrike = nullptr; SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); - SkFindAndPlaceGlyph::ProcessPosText( paint.skPaint().getTextEncoding(), text, byteLength, offset, viewMatrix, pos, scalarsPerPosition, paint.skPaint().getTextAlign(), cache, @@ -450,6 +435,77 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, SkGlyphCache::AttachCache(cache); } +void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex, + const GrTextUtils::Paint& origPaint, const char text[], + size_t byteLength, SkScalar x, SkScalar y) { + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. + SkPaint paint(origPaint); + paint.setStyle(SkPaint::kFill_Style); + paint.setPathEffect(nullptr); + + SkTextToPathIter iter(text, byteLength, paint, true); + const SkPath* iterPath; + SkScalar xpos = 0; + while (iter.next(&iterPath, &xpos)) { + if (iterPath) { + blob->appendPathGlyph(runIndex, *iterPath, xpos + x, y, iter.getPathScale(), false); + } + } +} + +void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runIndex, + const SkSurfaceProps& props, + const GrTextUtils::Paint& origPaint, + const char text[], size_t byteLength, + const SkScalar pos[], int scalarsPerPosition, + const SkPoint& offset, SkScalar textRatio) { + SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + // setup our std paint, in hopes of getting hits in the cache + SkPaint paint(origPaint); + SkScalar matrixScale = paint.setupForAsPaths(); + matrixScale *= textRatio; + + // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. + paint.setStyle(SkPaint::kFill_Style); + paint.setPathEffect(nullptr); + + SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(), + paint.isDevKernText(), + true); + SkAutoGlyphCache autoCache(paint, &props, nullptr); + SkGlyphCache* cache = autoCache.getCache(); + + const char* stop = text + byteLength; + SkTextAlignProc alignProc(paint.getTextAlign()); + SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); + + while (text < stop) { + const SkGlyph& glyph = glyphCacheProc(cache, &text); + if (glyph.fWidth) { + const SkPath* path = cache->findPath(glyph); + if (path) { + SkPoint tmsLoc; + tmsProc(pos, &tmsLoc); + SkPoint loc; + alignProc(tmsLoc, glyph, &loc); + blob->appendPathGlyph(runIndex, *path, loc.fX, loc.fY, matrixScale, false); + } + } + pos += scalarsPerPosition; + } +} + void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache* fontCache, GrAtlasTextStrike** strike, const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, @@ -467,6 +523,7 @@ void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, if (!glyph) { return; } + glyph->fTooLargeForAtlas = glyph->fTooLargeForAtlas; SkASSERT(skGlyph.fWidth == glyph->width()); SkASSERT(skGlyph.fHeight == glyph->height()); @@ -675,11 +732,10 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, SkTDArray<char> fallbackTxt; SkTDArray<SkScalar> fallbackPos; - SkTDArray<char> bigFallbackTxt; - SkTDArray<SkScalar> bigFallbackPos; + bool useScaledFallback = false; SkScalar textSize = paint.skPaint().getTextSize(); SkScalar maxTextSize = fontCache->getGlyphSizeLimit(); - SkScalar bigFallbackTextSize = maxTextSize; + SkScalar scaledFallbackTextSize = maxTextSize; SkScalar maxScale = viewMatrix.getMaxScale(); bool hasWCoord = viewMatrix.hasPerspective() || fDistanceFieldVerticesAlwaysHaveW; @@ -723,19 +779,30 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, y - advanceY, paint.filteredPremulColor(), cache, textRatio); } else { // can't append color glyph to SDF batch, send to fallback + + // all fallback glyphs need to use the same descriptor, so once + // we have to scale one, we have to scale all of them SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*textRatio; - SkScalar scaledGlyphSize = maxDim*maxScale; + if (!useScaledFallback) { + SkScalar scaledGlyphSize = maxDim * maxScale; + if (!viewMatrix.hasPerspective() && scaledGlyphSize > maxTextSize) { + useScaledFallback = true; + // rescale previous glyph positions to match text scale + for (int i = 0; i < fallbackPos.count(); ++i) { + fallbackPos[i] *= maxScale; + } + } + } - if (!viewMatrix.hasPerspective() && scaledGlyphSize > maxTextSize) { - bigFallbackTxt.append(SkToInt(text - lastText), lastText); - *bigFallbackPos.append() = maxScale*pos[0]; + fallbackTxt.append(SkToInt(text - lastText), lastText); + if (useScaledFallback) { + *fallbackPos.append() = maxScale*pos[0]; if (2 == scalarsPerPosition) { - *bigFallbackPos.append() = maxScale*pos[1]; + *fallbackPos.append() = maxScale*pos[1]; } SkScalar glyphTextSize = SkScalarFloorToScalar(maxTextSize*textSize/maxDim); - bigFallbackTextSize = SkTMin(glyphTextSize, bigFallbackTextSize); + scaledFallbackTextSize = SkTMin(glyphTextSize, scaledFallbackTextSize); } else { - fallbackTxt.append(SkToInt(text - lastText), lastText); *fallbackPos.append() = pos[0]; if (2 == scalarsPerPosition) { *fallbackPos.append() = pos[1]; @@ -747,33 +814,35 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, } SkGlyphCache::AttachCache(cache); + if (fallbackTxt.count()) { blob->initOverride(runIndex); - GrAtlasTextContext::DrawBmpPosText(blob, runIndex, fontCache, props, paint, - scalerContextFlags, viewMatrix, fallbackTxt.begin(), - fallbackTxt.count(), fallbackPos.begin(), - scalarsPerPosition, offset, SK_Scalar1); + if (useScaledFallback) { + // Set up paint and matrix to scale glyphs + SkPaint scaledPaint(paint); + scaledPaint.setTextSize(scaledFallbackTextSize); + // remove maxScale from viewMatrix and move it into textRatio + // this keeps the base glyph size consistent regardless of matrix scale + SkMatrix modMatrix(viewMatrix); + SkScalar invScale = SkScalarInvert(maxScale); + modMatrix.preScale(invScale, invScale); + SkScalar scaledFallbackTextRatio = textSize * maxScale / scaledFallbackTextSize; + SkPoint modOffset(offset); + modOffset *= maxScale; + GrTextUtils::Paint textPaint(&scaledPaint, paint.dstColorSpaceInfo()); + GrAtlasTextContext::DrawBmpPosText(blob, runIndex, fontCache, props, textPaint, + scalerContextFlags, modMatrix, fallbackTxt.begin(), + fallbackTxt.count(), fallbackPos.begin(), + scalarsPerPosition, modOffset, + scaledFallbackTextRatio); + } else { + GrAtlasTextContext::DrawBmpPosText(blob, runIndex, fontCache, props, paint, + scalerContextFlags, viewMatrix, fallbackTxt.begin(), + fallbackTxt.count(), fallbackPos.begin(), + scalarsPerPosition, offset, SK_Scalar1); + } } - if (bigFallbackTxt.count()) { - // Set up paint and matrix to scale glyphs - blob->initOverride(runIndex); - SkPaint largePaint(paint); - largePaint.setTextSize(bigFallbackTextSize); - // remove maxScale from viewMatrix and move it into textRatio - // this keeps the base glyph size consistent regardless of matrix scale - SkMatrix modMatrix(viewMatrix); - SkScalar invScale = SkScalarInvert(maxScale); - modMatrix.preScale(invScale, invScale); - SkScalar bigFallbackTextRatio = textSize*maxScale/bigFallbackTextSize; - SkPoint modOffset(offset); - modOffset *= maxScale; - GrTextUtils::Paint textPaint(&largePaint, paint.dstColorSpaceInfo()); - GrAtlasTextContext::DrawBmpPosText(blob, runIndex, fontCache, props, textPaint, - scalerContextFlags, modMatrix, bigFallbackTxt.begin(), - bigFallbackTxt.count(), bigFallbackPos.begin(), - scalarsPerPosition, modOffset, bigFallbackTextRatio); - } } // TODO: merge with BmpAppendGlyph |