aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/text
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2018-02-15 14:05:24 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-16 18:07:36 +0000
commitc401bb9c14332aa6c4c19d7f299f1512bf07c6a2 (patch)
treea14f993a69161df69b3b40699e9c497873979ff0 /src/gpu/text
parentcbf66a22130a1fd13285bb65d3a0d7ee6b4e8ab3 (diff)
Add full scaling for color emoji.
Bug: skia:7562 Change-Id: If6788a5004fe060b42a4e437f9b8c18459623225 Reviewed-on: https://skia-review.googlesource.com/106821 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
Diffstat (limited to 'src/gpu/text')
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp253
-rw-r--r--src/gpu/text/GrAtlasTextContext.h50
-rw-r--r--src/gpu/text/GrTextUtils.cpp29
-rw-r--r--src/gpu/text/GrTextUtils.h20
4 files changed, 237 insertions, 115 deletions
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 66cc0d4308..06282e103e 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -18,7 +18,6 @@
#include "SkMakeUnique.h"
#include "SkMaskFilterBase.h"
#include "SkTextMapStateProc.h"
-#include "SkTextToPathIter.h"
#include "ops/GrMeshDrawOp.h"
@@ -242,12 +241,12 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
case SkTextBlob::kHorizontal_Positioning:
DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags,
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1,
- SkPoint::Make(x, y + offset.y()), SK_Scalar1);
+ SkPoint::Make(x, y + offset.y()));
break;
case SkTextBlob::kFull_Positioning:
DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags,
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2,
- SkPoint::Make(x, y), SK_Scalar1);
+ SkPoint::Make(x, y));
break;
}
}
@@ -307,7 +306,7 @@ GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
text, byteLength, pos, scalarsPerPosition, offset);
} else {
DrawBmpPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text,
- byteLength, pos, scalarsPerPosition, offset, SK_Scalar1);
+ byteLength, pos, scalarsPerPosition, offset);
}
return blob;
}
@@ -378,7 +377,8 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
blob->setHasBitmap();
if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) {
- DrawBmpTextAsPaths(blob, runIndex, paint, text, byteLength, x, y);
+ DrawBmpTextAsPaths(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix,
+ text, byteLength, x, y);
return;
}
GrAtlasTextStrike* currStrike = nullptr;
@@ -403,8 +403,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
const char text[], size_t byteLength, const SkScalar pos[],
- int scalarsPerPosition, const SkPoint& offset,
- SkScalar textRatio) {
+ int scalarsPerPosition, const SkPoint& offset) {
SkASSERT(byteLength == 0 || text != nullptr);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
@@ -417,8 +416,8 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
blob->setHasBitmap();
if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) {
- DrawBmpPosTextAsPaths(blob, runIndex, props, paint, text, byteLength,
- pos, scalarsPerPosition, offset, textRatio);
+ DrawBmpPosTextAsPaths(blob, runIndex, fontCache, props, paint, scalerContextFlags,
+ viewMatrix, text, byteLength, pos, scalarsPerPosition, offset);
return;
}
@@ -433,14 +432,18 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph,
SkScalarFloorToScalar(position.fX),
SkScalarFloorToScalar(position.fY),
- paint.filteredPremulColor(), cache, textRatio);
+ paint.filteredPremulColor(), cache, SK_Scalar1);
});
SkGlyphCache::AttachCache(cache);
}
void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
- const GrTextUtils::Paint& origPaint, const char text[],
+ GrAtlasGlyphCache* fontCache,
+ const SkSurfaceProps& props,
+ const GrTextUtils::Paint& origPaint,
+ SkScalerContextFlags scalerContextFlags,
+ const SkMatrix& viewMatrix, const char text[],
size_t byteLength, SkScalar x, SkScalar y) {
// nothing to draw
if (text == nullptr || byteLength == 0) {
@@ -448,26 +451,41 @@ void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
}
// 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);
+ SkPaint pathPaint(origPaint);
+ pathPaint.setStyle(SkPaint::kFill_Style);
+ pathPaint.setPathEffect(nullptr);
- SkTextToPathIter iter(text, byteLength, paint, true);
+ GrTextUtils::PathTextIter iter(text, byteLength, pathPaint, true);
+ FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint.getTextSize(),
+ fontCache->getGlyphSizeLimit(),
+ iter.getPathScale());
+
+ const SkGlyph* iterGlyph;
const SkPath* iterPath;
SkScalar xpos = 0;
- while (iter.next(&iterPath, &xpos)) {
- if (iterPath) {
+ const char* lastText = text;
+ while (iter.next(&iterGlyph, &iterPath, &xpos)) {
+ if (iterGlyph) {
+ SkPoint pos = SkPoint::Make(xpos + x, y);
+ fallbackTextHelper.appendText(*iterGlyph, iter.getText() - lastText, lastText, pos);
+ } else if (iterPath) {
blob->appendPathGlyph(runIndex, *iterPath, xpos + x, y, iter.getPathScale(), false);
}
+ lastText = iter.getText();
}
+
+ fallbackTextHelper.drawText(blob, runIndex, fontCache, props, origPaint, scalerContextFlags);
}
void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
+ GrAtlasGlyphCache* fontCache,
const SkSurfaceProps& props,
const GrTextUtils::Paint& origPaint,
+ SkScalerContextFlags scalerContextFlags,
+ const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
- const SkPoint& offset, SkScalar textRatio) {
+ const SkPoint& offset) {
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
// nothing to draw
@@ -476,38 +494,47 @@ void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runInd
}
// setup our std paint, in hopes of getting hits in the cache
- SkPaint paint(origPaint);
- SkScalar matrixScale = paint.setupForAsPaths();
- matrixScale *= textRatio;
+ SkPaint pathPaint(origPaint);
+ SkScalar matrixScale = pathPaint.setupForAsPaths();
+ FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint.getTextSize(), matrixScale,
+ fontCache->getGlyphSizeLimit());
// Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
- paint.setStyle(SkPaint::kFill_Style);
- paint.setPathEffect(nullptr);
+ pathPaint.setStyle(SkPaint::kFill_Style);
+ pathPaint.setPathEffect(nullptr);
- SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
- paint.isDevKernText(),
- true);
- SkAutoGlyphCache autoCache(paint, &props, nullptr);
+ SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(pathPaint.getTextEncoding(),
+ pathPaint.isDevKernText(),
+ true);
+ SkAutoGlyphCache autoCache(pathPaint, &props, nullptr);
SkGlyphCache* cache = autoCache.getCache();
const char* stop = text + byteLength;
- SkTextAlignProc alignProc(paint.getTextAlign());
+ const char* lastText = text;
+ SkTextAlignProc alignProc(pathPaint.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);
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+ SkPoint loc;
+ alignProc(tmsLoc, glyph, &loc);
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+ fallbackTextHelper.appendText(glyph, text - lastText, lastText, loc);
+ } else {
+ const SkPath* path = cache->findPath(glyph);
+ if (path) {
+ blob->appendPathGlyph(runIndex, *path, loc.fX, loc.fY, matrixScale, false);
+ }
}
}
+ lastText = text;
pos += scalarsPerPosition;
}
+
+ fallbackTextHelper.drawText(blob, runIndex, fontCache, props, origPaint, scalerContextFlags);
}
void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
@@ -732,15 +759,6 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
return;
}
- SkTDArray<char> fallbackTxt;
- SkTDArray<SkScalar> fallbackPos;
-
- bool useScaledFallback = false;
- SkScalar textSize = paint.skPaint().getTextSize();
- SkScalar maxTextSize = fontCache->getGlyphSizeLimit();
- SkScalar scaledFallbackTextSize = maxTextSize;
- SkScalar maxScale = viewMatrix.getMaxScale();
-
bool hasWCoord = viewMatrix.hasPerspective() || fDistanceFieldVerticesAlwaysHaveW;
// Setup distance field paint and text ratio
@@ -751,6 +769,11 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(),
paint.skPaint().isAntiAlias(), hasWCoord);
+ FallbackTextHelper fallbackTextHelper(viewMatrix,
+ paint.skPaint().getTextSize(),
+ fontCache->getGlyphSizeLimit(),
+ textRatio);
+
GrAtlasTextStrike* currStrike = nullptr;
// We apply the fake-gamma by altering the distance in the shader, so we ignore the
@@ -771,46 +794,17 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
const SkGlyph& glyph = glyphCacheProc(cache, &text);
if (glyph.fWidth) {
- SkScalar x = offset.x() + pos[0];
- SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);
-
- SkScalar advanceX = SkFloatToScalar(glyph.fAdvanceX) * alignMul * textRatio;
- SkScalar advanceY = SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio;
+ SkPoint glyphPos(offset);
+ glyphPos.fX += pos[0] - SkFloatToScalar(glyph.fAdvanceX) * alignMul * textRatio;
+ glyphPos.fY += (2 == scalarsPerPosition ? pos[1] : 0) -
+ SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio;
if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
- DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, x - advanceX,
- y - advanceY, paint.filteredPremulColor(), cache, textRatio);
+ DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, glyphPos.fX,
+ glyphPos.fY, 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;
- 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;
- }
- }
- }
-
- fallbackTxt.append(SkToInt(text - lastText), lastText);
- if (useScaledFallback) {
- *fallbackPos.append() = maxScale*pos[0];
- if (2 == scalarsPerPosition) {
- *fallbackPos.append() = maxScale*pos[1];
- }
- SkScalar glyphTextSize = SkScalarFloorToScalar(maxTextSize*textSize/maxDim);
- scaledFallbackTextSize = SkTMin(glyphTextSize, scaledFallbackTextSize);
- } else {
- *fallbackPos.append() = pos[0];
- if (2 == scalarsPerPosition) {
- *fallbackPos.append() = pos[1];
- }
- }
+ fallbackTextHelper.appendText(glyph, SkToInt(text - lastText), lastText, glyphPos);
}
}
pos += scalarsPerPosition;
@@ -818,34 +812,8 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
SkGlyphCache::AttachCache(cache);
- if (fallbackTxt.count()) {
- blob->initOverride(runIndex);
- 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);
- }
- }
-
+ fallbackTextHelper.drawText(blob, runIndex, fontCache, props, paint,
+ scalerContextFlags);
}
// TODO: merge with BmpAppendGlyph
@@ -884,6 +852,75 @@ void GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
///////////////////////////////////////////////////////////////////////////////////////////////////
+void GrAtlasTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, int count,
+ const char* text, SkPoint glyphPos) {
+ SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio;
+ if (!fUseScaledFallback) {
+ SkScalar scaledGlyphSize = maxDim * fMaxScale;
+ if (!fViewMatrix.hasPerspective() && scaledGlyphSize > fMaxTextSize) {
+ fUseScaledFallback = true;
+ }
+ }
+
+ fFallbackTxt.append(count, text);
+ if (fUseScaledFallback) {
+ SkScalar glyphTextSize = SkScalarFloorToScalar(fMaxTextSize*fTextSize / maxDim);
+ fScaledFallbackTextSize = SkTMin(glyphTextSize, fScaledFallbackTextSize);
+ }
+ *fFallbackPos.append() = glyphPos;
+}
+
+void GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int runIndex,
+ GrAtlasGlyphCache* fontCache,
+ const SkSurfaceProps& props,
+ const GrTextUtils::Paint& paint,
+ SkScalerContextFlags scalerContextFlags) {
+ if (fFallbackTxt.count()) {
+ blob->initOverride(runIndex);
+ blob->setHasBitmap();
+ SkGlyphCache* cache = nullptr;
+ const SkPaint& skPaint = paint.skPaint();
+ SkPaint::GlyphCacheProc glyphCacheProc =
+ SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(),
+ skPaint.isDevKernText(), true);
+ SkColor textColor = paint.filteredPremulColor();
+ SkScalar textRatio = SK_Scalar1;
+ fViewMatrix.mapPoints(fFallbackPos.begin(), fFallbackPos.count());
+ if (fUseScaledFallback) {
+ // Set up paint and matrix to scale glyphs
+ SkPaint scaledPaint(skPaint);
+ scaledPaint.setTextSize(fScaledFallbackTextSize);
+ // remove maxScale from viewMatrix and move it into textRatio
+ // this keeps the base glyph size consistent regardless of matrix scale
+ SkMatrix modMatrix(fViewMatrix);
+ SkScalar invScale = SkScalarInvert(fMaxScale);
+ modMatrix.preScale(invScale, invScale);
+ textRatio = fTextSize * fMaxScale / fScaledFallbackTextSize;
+ cache = blob->setupCache(runIndex, props, scalerContextFlags, scaledPaint,
+ &modMatrix);
+ } else {
+ cache = blob->setupCache(runIndex, props, scalerContextFlags, paint,
+ &fViewMatrix);
+ }
+
+ GrAtlasTextStrike* currStrike = nullptr;
+ const char* text = fFallbackTxt.begin();
+ const char* stop = text + fFallbackTxt.count();
+ SkPoint* glyphPos = fFallbackPos.begin();
+ while (text < stop) {
+ const SkGlyph& glyph = glyphCacheProc(cache, &text);
+ GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph,
+ glyphPos->fX, glyphPos->fY, textColor,
+ cache, textRatio);
+ glyphPos++;
+ }
+
+ SkGlyphCache::AttachCache(cache);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
#if GR_TEST_UTILS
#include "GrRenderTargetContext.h"
diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h
index 360f6ddbec..207dd67206 100644
--- a/src/gpu/text/GrAtlasTextContext.h
+++ b/src/gpu/text/GrAtlasTextContext.h
@@ -58,6 +58,39 @@ public:
private:
GrAtlasTextContext(const Options& options);
+ class FallbackTextHelper {
+ public:
+ FallbackTextHelper(const SkMatrix& viewMatrix,
+ SkScalar textSize,
+ SkScalar maxTextSize,
+ SkScalar textRatio)
+ : fViewMatrix(viewMatrix)
+ , fTextRatio(textRatio)
+ , fTextSize(textSize)
+ , fMaxTextSize(maxTextSize)
+ , fScaledFallbackTextSize(maxTextSize)
+ , fUseScaledFallback(false) {
+ fMaxScale = viewMatrix.getMaxScale();
+ }
+
+ void appendText(const SkGlyph& glyph, int count, const char* text, SkPoint glyphPos);
+ void drawText(GrAtlasTextBlob* blob, int runIndex,
+ GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
+ const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags);
+
+ private:
+ SkTDArray<char> fFallbackTxt;
+ SkTDArray<SkPoint> fFallbackPos;
+
+ const SkMatrix& fViewMatrix;
+ SkScalar fTextRatio;
+ SkScalar fTextSize;
+ SkScalar fMaxTextSize;
+ SkScalar fScaledFallbackTextSize;
+ SkScalar fMaxScale;
+ bool fUseScaledFallback;
+ };
+
// sets up the descriptor on the blob and returns a detached cache. Client must attach
static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
// Determines if we need to use fake gamma (and contrast boost):
@@ -104,18 +137,21 @@ private:
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
const char text[], size_t byteLength, const SkScalar pos[],
- int scalarsPerPosition, const SkPoint& offset,
- SkScalar textRatio);
+ int scalarsPerPosition, const SkPoint& offset);
- static void DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
- const GrTextUtils::Paint& paint, const char text[],
+ static void DrawBmpTextAsPaths(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ const SkSurfaceProps&, const GrTextUtils::Paint& paint,
+ SkScalerContextFlags scalerContextFlags,
+ const SkMatrix& viewMatrix, const char text[],
size_t byteLength, SkScalar x, SkScalar y);
- static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex,
- const SkSurfaceProps& props, const GrTextUtils::Paint& paint,
+ static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ const SkSurfaceProps&, const GrTextUtils::Paint& paint,
+ SkScalerContextFlags scalerContextFlags,
+ const SkMatrix& viewMatrix,
const char text[], size_t byteLength,
const SkScalar pos[], int scalarsPerPosition,
- const SkPoint& offset, SkScalar textRatio);
+ const SkPoint& offset);
// functions for appending distance field text
bool canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix,
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index 56c1d3309a..680e262766 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -75,3 +75,32 @@ bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) {
return paint.getMaskFilter() || paint.getPathEffect() ||
paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style;
}
+
+bool GrTextUtils::PathTextIter::next(const SkGlyph** skGlyph, const SkPath** path, SkScalar* xpos) {
+ SkASSERT(skGlyph);
+ SkASSERT(path);
+ SkASSERT(xpos);
+ if (fText < fStop) {
+ const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
+
+ fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
+ SkASSERT(0 == fXYIndex || 1 == fXYIndex);
+ fPrevAdvance = SkFloatToScalar((&glyph.fAdvanceX)[fXYIndex]);
+
+ if (glyph.fWidth) {
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+ *skGlyph = &glyph;
+ *path = nullptr;
+ } else {
+ *skGlyph = nullptr;
+ *path = fCache->findPath(glyph);
+ }
+ } else {
+ *skGlyph = nullptr;
+ *path = nullptr;
+ }
+ *xpos = fXPos;
+ return true;
+ }
+ return false;
+}
diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h
index 58318e8fe3..5fe38fe773 100644
--- a/src/gpu/text/GrTextUtils.h
+++ b/src/gpu/text/GrTextUtils.h
@@ -13,6 +13,7 @@
#include "SkColorFilter.h"
#include "SkPaint.h"
#include "SkScalar.h"
+#include "SkTextToPathIter.h"
#include "SkTLazy.h"
class GrAtlasGlyphCache;
@@ -127,6 +128,25 @@ public:
static uint32_t FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint);
static bool ShouldDisableLCD(const SkPaint& paint);
+
+ class PathTextIter : SkTextBaseIter {
+ public:
+ PathTextIter(const char text[], size_t length, const SkPaint& paint,
+ bool applyStrokeAndPathEffects)
+ : SkTextBaseIter(text, length, paint, applyStrokeAndPathEffects) {
+ }
+
+ const SkPaint& getPaint() const { return fPaint; }
+ SkScalar getPathScale() const { return fScale; }
+ const char* getText() const { return fText; }
+
+ /**
+ * Returns false when all of the text has been consumed
+ * Will set skGlyph if the maskformat is ARGB, and path otherwise. The other will be null.
+ * If the glyph is zero-width, both will be null.
+ */
+ bool next(const SkGlyph** skGlyph, const SkPath** path, SkScalar* xpos);
+ };
};
#endif