aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/text/GrAtlasTextContext.cpp
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2018-02-06 11:14:20 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-06 17:28:16 +0000
commit2fb7c8aef57e4b94d5215e618d8c3b4cccd35edf (patch)
treef9d56b011d402a858e3c69717605f6f78cb2693e /src/gpu/text/GrAtlasTextContext.cpp
parente1ddce57ea78ed1ec1a7297cb9799b5a64aaa937 (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.cpp229
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