aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2018-02-08 16:14:48 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-08 22:42:40 +0000
commit54d9c889fb6aca043a7b005d61de4e0e65a3ae53 (patch)
treed19bd15855296d86798d8b103c297d7f872fc330
parent6ba15ecb1cdd75f57abae8eeece7886aa8f28832 (diff)
Cleanup of large text rendering, take 2.
* 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 * Set paint flags correctly for paths Bug: skia:7562 Change-Id: I9455eda2867860a713fbdbbda79c74109e95f9f2 Reviewed-on: https://skia-review.googlesource.com/105020 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r--gm/glyph_pos.cpp2
-rw-r--r--src/gpu/text/GrAtlasTextBlob.cpp266
-rw-r--r--src/gpu/text/GrAtlasTextBlob.h93
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp235
-rw-r--r--src/gpu/text/GrAtlasTextContext.h13
-rw-r--r--src/gpu/text/GrTextUtils.cpp87
-rw-r--r--src/gpu/text/GrTextUtils.h15
7 files changed, 314 insertions, 397 deletions
diff --git a/gm/glyph_pos.cpp b/gm/glyph_pos.cpp
index cfc318d4b4..ff2a432f8a 100644
--- a/gm/glyph_pos.cpp
+++ b/gm/glyph_pos.cpp
@@ -26,7 +26,7 @@ static void drawTestCase(SkCanvas* canvas,
static void draw_gm(SkCanvas* canvas,
SkScalar strokeWidth,
SkPaint::Style strokeStyle) {
- // There's a black pixel at 40, 40 for reference.
+ // There's a black pixel at 40, 40 for reference.
canvas->drawPoint(40, 40, SkPaint());
// Two reference images.
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 887addd25c..e80576187b 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -15,6 +15,7 @@
#include "SkGlyphCache.h"
#include "SkMaskFilterBase.h"
#include "SkTextBlobRunIterator.h"
+#include "SkTextToPathIter.h"
#include "ops/GrAtlasTextOp.h"
sk_sp<GrAtlasTextBlob> GrAtlasTextBlob::Make(GrMemoryPool* pool, int glyphCount, int runCount) {
@@ -73,14 +74,22 @@ void GrAtlasTextBlob::appendGlyph(int runIndex,
GrAtlasTextStrike* strike,
GrGlyph* glyph,
SkGlyphCache* cache, const SkGlyph& skGlyph,
- SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP) {
+ SkScalar x, SkScalar y, SkScalar scale, bool preTransformed) {
if (positions.isEmpty()) {
return;
}
// If the glyph is too large we fall back to paths
if (glyph->fTooLargeForAtlas) {
- this->appendBigGlyph(glyph, cache, skGlyph, x, y, scale, treatAsBMP);
+ if (nullptr == glyph->fPath) {
+ const SkPath* glyphPath = cache->findPath(skGlyph);
+ if (!glyphPath) {
+ return;
+ }
+
+ glyph->fPath = new SkPath(*glyphPath);
+ }
+ this->appendPathGlyph(runIndex, *glyph->fPath, x, y, scale, preTransformed);
return;
}
@@ -140,17 +149,10 @@ void GrAtlasTextBlob::appendGlyph(int runIndex,
subRun->glyphAppended();
}
-void GrAtlasTextBlob::appendBigGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph,
- SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP) {
- if (nullptr == glyph->fPath) {
- const SkPath* glyphPath = cache->findPath(skGlyph);
- if (!glyphPath) {
- return;
- }
-
- glyph->fPath = new SkPath(*glyphPath);
- }
- fBigGlyphs.push_back(GrAtlasTextBlob::BigGlyph(*glyph->fPath, x, y, scale, treatAsBMP));
+void GrAtlasTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y,
+ SkScalar scale, bool preTransformed) {
+ Run& run = fRuns[runIndex];
+ run.fPathGlyphs.push_back(GrAtlasTextBlob::Run::PathGlyph(path, x, y, scale, preTransformed));
}
bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint,
@@ -273,62 +275,6 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp(
return op;
}
-inline void GrAtlasTextBlob::flushRun(GrTextUtils::Target* target, const GrClip& clip, int run,
- const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
- const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable,
- GrAtlasGlyphCache* cache) {
- // GrAtlasTextBlob::makeOp only takes uint16_t values for run and subRun indices.
- // Encountering something larger than this is highly unlikely, so we'll just not draw it.
- if (run >= (1 << 16)) {
- return;
- }
- int lastRun = SkTMin(fRuns[run].fSubRunInfo.count(), 1 << 16) - 1;
- for (int subRun = 0; subRun <= lastRun; subRun++) {
- const Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
- int glyphCount = info.glyphCount();
- if (0 == glyphCount) {
- continue;
- }
-
- bool skipClip = false;
- bool submitOp = true;
- SkIRect clipRect = SkIRect::MakeEmpty();
- SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
- SkRRect clipRRect;
- GrAA aa;
- // We can clip geometrically if we're not using SDFs,
- // and we have an axis-aligned rectangular non-AA clip
- if (!info.drawAsDistanceFields() && clip.isRRect(rtBounds, &clipRRect, &aa) &&
- clipRRect.isRect() && GrAA::kNo == aa) {
- skipClip = true;
- // We only need to do clipping work if the subrun isn't contained by the clip
- SkRect subRunBounds;
- this->computeSubRunBounds(&subRunBounds, run, subRun, viewMatrix, x, y);
- if (!clipRRect.getBounds().contains(subRunBounds)) {
- // If the subrun is completely outside, don't add an op for it
- if (!clipRRect.getBounds().intersects(subRunBounds)) {
- submitOp = false;
- } else {
- clipRRect.getBounds().round(&clipRect);
- }
- }
- }
-
- if (submitOp) {
- auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, clipRect,
- std::move(paint), props, distanceAdjustTable, cache, target);
- if (op) {
- if (skipClip) {
- target->addDrawOp(GrNoClip(), std::move(op));
- } else {
- target->addDrawOp(clip, std::move(op));
- }
- }
- }
- }
-}
-
static void calculate_translation(bool applyVM,
const SkMatrix& newViewMatrix, SkScalar newX, SkScalar newY,
const SkMatrix& currentViewMatrix, SkScalar currentX,
@@ -349,94 +295,95 @@ static void calculate_translation(bool applyVM,
}
}
-void GrAtlasTextBlob::flushBigGlyphs(GrTextUtils::Target* target,
- const GrClip& clip, const SkPaint& paint,
- const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
- const SkIRect& clipBounds) {
- SkScalar transX, transY;
- for (int i = 0; i < fBigGlyphs.count(); i++) {
- GrAtlasTextBlob::BigGlyph& bigGlyph = fBigGlyphs[i];
- calculate_translation(bigGlyph.fTreatAsBMP, viewMatrix, x, y,
- fInitialViewMatrix, fInitialX, fInitialY, &transX, &transY);
- SkMatrix ctm;
- ctm.setScale(bigGlyph.fScale, bigGlyph.fScale);
- ctm.postTranslate(bigGlyph.fX + transX, bigGlyph.fY + transY);
- if (!bigGlyph.fTreatAsBMP) {
- ctm.postConcat(viewMatrix);
- }
- target->drawPath(clip, bigGlyph.fPath, paint, ctm, nullptr, clipBounds);
- }
-}
-
-void GrAtlasTextBlob::flushBigRun(GrTextUtils::Target* target,
- const SkSurfaceProps& props, const SkTextBlobRunIterator& it,
- const GrClip& clip, const GrTextUtils::Paint& paint,
- SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
- const SkIRect& clipBounds, SkScalar x, SkScalar y) {
- size_t textLen = it.glyphCount() * sizeof(uint16_t);
- const SkPoint& offset = it.offset();
-
- GrTextUtils::RunPaint runPaint(&paint, drawFilter, props);
- if (!runPaint.modifyForRun(it)) {
- return;
- }
+void GrAtlasTextBlob::flush(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Target* target,
+ const SkSurfaceProps& props,
+ const GrDistanceFieldAdjustTable* distanceAdjustTable,
+ const GrTextUtils::Paint& paint, const GrClip& clip,
+ const SkMatrix& viewMatrix, const SkIRect& clipBounds,
+ SkScalar x, SkScalar y) {
- switch (it.positioning()) {
- case SkTextBlob::kDefault_Positioning:
- GrTextUtils::DrawBigText(target, clip, runPaint, viewMatrix,
- (const char*)it.glyphs(), textLen, x + offset.x(),
- y + offset.y(), clipBounds);
- break;
- case SkTextBlob::kHorizontal_Positioning:
- GrTextUtils::DrawBigPosText(target, props, clip, runPaint, viewMatrix,
- (const char*)it.glyphs(), textLen, it.pos(), 1,
- SkPoint::Make(x, y + offset.y()), clipBounds);
- break;
- case SkTextBlob::kFull_Positioning:
- GrTextUtils::DrawBigPosText(target, props, clip, runPaint, viewMatrix,
- (const char*)it.glyphs(), textLen, it.pos(), 2,
- SkPoint::Make(x, y), clipBounds);
- break;
- }
-}
+ // GrAtlasTextBlob::makeOp only takes uint16_t values for run and subRun indices.
+ // Encountering something larger than this is highly unlikely, so we'll just not draw it.
+ int lastRun = SkTMin(fRunCount, (1 << 16)) - 1;
+ GrTextUtils::RunPaint runPaint(&paint, nullptr, props);
+ for (int runIndex = 0; runIndex <= lastRun; runIndex++) {
+ Run& run = fRuns[runIndex];
+
+ // first flush any path glyphs
+ if (run.fPathGlyphs.count()) {
+ SkScalar transX, transY;
+ uint16_t paintFlags = run.fPaintFlags;
+ if (!runPaint.modifyForRun(
+ [paintFlags](SkPaint* p) {
+ p->setFlags((p->getFlags() & ~Run::kPaintFlagsMask) | paintFlags);
+ })) {
+ continue;
+ }
+ for (int i = 0; i < run.fPathGlyphs.count(); i++) {
+ GrAtlasTextBlob::Run::PathGlyph& pathGlyph = run.fPathGlyphs[i];
+ calculate_translation(pathGlyph.fPreTransformed, viewMatrix, x, y,
+ fInitialViewMatrix, fInitialX, fInitialY, &transX, &transY);
+ const SkMatrix& ctm = pathGlyph.fPreTransformed ? SkMatrix::I() : viewMatrix;
+ SkMatrix pathMatrix;
+ pathMatrix.setScale(pathGlyph.fScale, pathGlyph.fScale);
+ pathMatrix.postTranslate(pathGlyph.fX + transX, pathGlyph.fY + transY);
+ target->drawPath(clip, pathGlyph.fPath, runPaint, ctm, &pathMatrix, clipBounds);
+ }
+ }
-void GrAtlasTextBlob::flushCached(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Target* target,
- const SkTextBlob* blob, const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable,
- const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter,
- const GrClip& clip, const SkMatrix& viewMatrix,
- const SkIRect& clipBounds, SkScalar x, SkScalar y) {
- // We loop through the runs of the blob, flushing each. If any run is too large, then we flush
- // it as paths
- SkTextBlobRunIterator it(blob);
- for (int run = 0; !it.done(); it.next(), run++) {
- if (fRuns[run].fTooBigForAtlas) {
- this->flushBigRun(target, props, it, clip, paint, drawFilter, viewMatrix,
- clipBounds, x, y);
+ // then flush each subrun, if any
+ if (!run.fInitialized) {
continue;
}
- this->flushRun(target, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
- atlasGlyphCache);
- }
+ int lastSubRun = SkTMin(run.fSubRunInfo.count(), 1 << 16) - 1;
+ for (int subRun = 0; subRun <= lastSubRun; subRun++) {
+ const Run::SubRunInfo& info = run.fSubRunInfo[subRun];
+ int glyphCount = info.glyphCount();
+ if (0 == glyphCount) {
+ continue;
+ }
- // Now flush big glyphs
- this->flushBigGlyphs(target, clip, paint, viewMatrix, x, y, clipBounds);
-}
+ bool skipClip = false;
+ bool submitOp = true;
+ SkIRect clipRect = SkIRect::MakeEmpty();
+ SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
+ SkRRect clipRRect;
+ GrAA aa;
+ // We can clip geometrically if we're not using SDFs,
+ // and we have an axis-aligned rectangular non-AA clip
+ if (!info.drawAsDistanceFields() && clip.isRRect(rtBounds, &clipRRect, &aa) &&
+ clipRRect.isRect() && GrAA::kNo == aa) {
+ skipClip = true;
+ // We only need to do clipping work if the subrun isn't contained by the clip
+ SkRect subRunBounds;
+ this->computeSubRunBounds(&subRunBounds, runIndex, subRun, viewMatrix, x, y);
+ if (!clipRRect.getBounds().contains(subRunBounds)) {
+ // If the subrun is completely outside, don't add an op for it
+ if (!clipRRect.getBounds().intersects(subRunBounds)) {
+ submitOp = false;
+ }
+ else {
+ clipRRect.getBounds().round(&clipRect);
+ }
+ }
+ }
-void GrAtlasTextBlob::flushThrowaway(GrAtlasGlyphCache* atlasGlyphCache,
- GrTextUtils::Target* target,
- const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable,
- const GrTextUtils::Paint& paint, const GrClip& clip,
- const SkMatrix& viewMatrix, const SkIRect& clipBounds,
- SkScalar x, SkScalar y) {
- for (int run = 0; run < fRunCount; run++) {
- this->flushRun(target, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
- atlasGlyphCache);
- }
+ if (submitOp) {
+ auto op = this->makeOp(info, glyphCount, runIndex, subRun, viewMatrix, x, y,
+ clipRect, std::move(paint), props, distanceAdjustTable,
+ atlasGlyphCache, target);
+ if (op) {
+ if (skipClip) {
+ target->addDrawOp(GrNoClip(), std::move(op));
+ }
+ else {
+ target->addDrawOp(clip, std::move(op));
+ }
+ }
+ }
+ }
- // Now flush big glyphs
- this->flushBigGlyphs(target, clip, paint, viewMatrix, x, y, clipBounds);
+ }
}
std::unique_ptr<GrDrawOp> GrAtlasTextBlob::test_makeOp(
@@ -462,15 +409,6 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo
SkASSERT_RELEASE(l.fStrokeInfo.fMiterLimit == r.fStrokeInfo.fMiterLimit);
SkASSERT_RELEASE(l.fStrokeInfo.fJoin == r.fStrokeInfo.fJoin);
- SkASSERT_RELEASE(l.fBigGlyphs.count() == r.fBigGlyphs.count());
- for (int i = 0; i < l.fBigGlyphs.count(); i++) {
- const BigGlyph& lBigGlyph = l.fBigGlyphs[i];
- const BigGlyph& rBigGlyph = r.fBigGlyphs[i];
-
- SkASSERT_RELEASE(lBigGlyph.fPath == rBigGlyph.fPath);
- // We can't assert that these have the same translations
- }
-
SkASSERT_RELEASE(l.fKey == r.fKey);
//SkASSERT_RELEASE(l.fPaintColor == r.fPaintColor); // Colors might not actually be identical
SkASSERT_RELEASE(l.fMaxMinScale == r.fMaxMinScale);
@@ -506,7 +444,6 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo
// color can be changed
//SkASSERT(lRun.fColor == rRun.fColor);
SkASSERT_RELEASE(lRun.fInitialized == rRun.fInitialized);
- SkASSERT_RELEASE(lRun.fTooBigForAtlas == rRun.fTooBigForAtlas);
SkASSERT_RELEASE(lRun.fSubRunInfo.count() == rRun.fSubRunInfo.count());
for(int j = 0; j < lRun.fSubRunInfo.count(); j++) {
@@ -533,6 +470,15 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo
SkASSERT_RELEASE(lSubRun.drawAsDistanceFields() == rSubRun.drawAsDistanceFields());
SkASSERT_RELEASE(lSubRun.hasUseLCDText() == rSubRun.hasUseLCDText());
}
+
+ SkASSERT_RELEASE(lRun.fPathGlyphs.count() == rRun.fPathGlyphs.count());
+ for (int i = 0; i < lRun.fPathGlyphs.count(); i++) {
+ const Run::PathGlyph& lPathGlyph = lRun.fPathGlyphs[i];
+ const Run::PathGlyph& rPathGlyph = rRun.fPathGlyphs[i];
+
+ SkASSERT_RELEASE(lPathGlyph.fPath == rPathGlyph.fPath);
+ // We can't assert that these have the same translations
+ }
}
}
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 12a80c49d3..9132684622 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -142,8 +142,8 @@ public:
subRun.setHasWCoord(hasWCoord);
}
- void setRunTooBigForAtlas(int runIndex) {
- fRuns[runIndex].fTooBigForAtlas = true;
+ void setRunPaintFlags(int runIndex, uint16_t paintFlags) {
+ fRuns[runIndex].fPaintFlags = paintFlags & Run::kPaintFlagsMask;
}
void setMinAndMaxScale(SkScalar scaledMax, SkScalar scaledMin) {
@@ -175,7 +175,11 @@ public:
GrAtlasTextStrike* strike,
GrGlyph* glyph,
SkGlyphCache*, const SkGlyph& skGlyph,
- SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP);
+ SkScalar x, SkScalar y, SkScalar scale, bool preTransformed);
+
+ // Appends a glyph to the blob as a path only.
+ void appendPathGlyph(int runIndex, const SkPath& path,
+ SkScalar x, SkScalar y, SkScalar scale, bool preTransformed);
static size_t GetVertexStride(GrMaskFormat maskFormat, bool isDistanceFieldWithWCoord) {
switch (maskFormat) {
@@ -193,19 +197,11 @@ public:
bool mustRegenerate(const GrTextUtils::Paint&, const SkMaskFilterBase::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
- // flush a GrAtlasTextBlob associated with a SkTextBlob
- void flushCached(GrAtlasGlyphCache*, GrTextUtils::Target*, const SkTextBlob* blob,
- const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable,
- const GrTextUtils::Paint&, SkDrawFilter* drawFilter, const GrClip& clip,
- const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y);
-
- // flush a throwaway GrAtlasTextBlob *not* associated with an SkTextBlob
- void flushThrowaway(GrAtlasGlyphCache*, GrTextUtils::Target*, const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable,
- const GrTextUtils::Paint& paint, const GrClip& clip,
- const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
- SkScalar y);
+ void flush(GrAtlasGlyphCache*, GrTextUtils::Target*, const SkSurfaceProps& props,
+ const GrDistanceFieldAdjustTable* distanceAdjustTable,
+ const GrTextUtils::Paint& paint, const GrClip& clip,
+ const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
+ SkScalar y);
void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
@@ -285,24 +281,6 @@ private:
, fMinMaxScale(SK_ScalarMax)
, fTextType(0) {}
- void appendBigGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph,
- SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP);
-
- inline void flushRun(GrTextUtils::Target*, const GrClip&, int run, const SkMatrix& viewMatrix,
- SkScalar x, SkScalar y, const GrTextUtils::Paint& paint,
- const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable,
- GrAtlasGlyphCache* cache);
-
- void flushBigGlyphs(GrTextUtils::Target*, const GrClip& clip,
- const SkPaint& paint, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
- const SkIRect& clipBounds);
-
- void flushBigRun(GrTextUtils::Target*, const SkSurfaceProps& props,
- const SkTextBlobRunIterator& it, const GrClip& clip,
- const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter,
- const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
- SkScalar y);
// This function will only be called when we are generating a blob from scratch. We record the
// initial view matrix and initial offsets(x,y), because we record vertex bounds relative to
@@ -347,9 +325,8 @@ private:
* would greatly increase the memory of these cached items.
*/
struct Run {
- Run()
- : fInitialized(false)
- , fTooBigForAtlas(false) {
+ Run() : fPaintFlags(0)
+ , fInitialized(false) {
// To ensure we always have one subrun, we push back a fresh run here
fSubRunInfo.push_back();
}
@@ -495,8 +472,31 @@ private:
// will have different descriptors. If fOverrideDescriptor is non-nullptr, then it
// will be used in place of the run's descriptor to regen texture coords
std::unique_ptr<SkAutoDescriptor> fOverrideDescriptor; // df properties
- bool fInitialized;
- bool fTooBigForAtlas;
+
+ // Any glyphs that can't be rendered with the base or override descriptor
+ // are rendered as paths
+ struct PathGlyph {
+ PathGlyph(const SkPath& path, SkScalar x, SkScalar y, SkScalar scale, bool preXformed)
+ : fPath(path)
+ , fX(x)
+ , fY(y)
+ , fScale(scale)
+ , fPreTransformed(preXformed) {}
+ SkPath fPath;
+ SkScalar fX;
+ SkScalar fY;
+ SkScalar fScale;
+ bool fPreTransformed;
+ };
+
+ SkTArray<PathGlyph> fPathGlyphs;
+
+ struct {
+ unsigned fPaintFlags : 16; // needed mainly for rendering paths
+ bool fInitialized : 1;
+ };
+ // the only flags we need to set
+ static constexpr auto kPaintFlagsMask = SkPaint::kAntiAlias_Flag;
}; // Run
inline std::unique_ptr<GrAtlasTextOp> makeOp(
@@ -506,20 +506,6 @@ private:
const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
GrTextUtils::Target*);
- struct BigGlyph {
- BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy, SkScalar scale, bool treatAsBMP)
- : fPath(path)
- , fScale(scale)
- , fX(vx)
- , fY(vy)
- , fTreatAsBMP(treatAsBMP) {}
- SkPath fPath;
- SkScalar fScale;
- SkScalar fX;
- SkScalar fY;
- bool fTreatAsBMP;
- };
-
struct StrokeInfo {
SkScalar fFrameWidth;
SkScalar fMiterLimit;
@@ -538,7 +524,6 @@ private:
GrMemoryPool* fPool;
SkMaskFilterBase::BlurRec fBlurRec;
StrokeInfo fStrokeInfo;
- SkTArray<BigGlyph> fBigGlyphs;
Key fKey;
SkMatrix fInitialViewMatrix;
SkMatrix fInitialViewMatrixInverse;
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 1dce4e0d44..63b3d3ddbd 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,
@@ -209,9 +204,11 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
size_t textLen = glyphCount * sizeof(uint16_t);
const SkPoint& offset = it.offset();
cacheBlob->push_back_run(run);
- if (!runPaint.modifyForRun(it)) {
+ if (!runPaint.modifyForRun([it](SkPaint* p) { it.applyFontToPaint(p); })) {
continue;
}
+ cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags());
+
if (this->canDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) {
switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning: {
@@ -235,8 +232,6 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
break;
}
}
- } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
- cacheBlob->setRunTooBigForAtlas(run);
} else {
switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning:
@@ -275,6 +270,7 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache,
}
sk_sp<GrAtlasTextBlob> blob = blobCache->makeBlob(glyphCount, 1);
blob->initThrowawayBlob(viewMatrix, x, y);
+ blob->setRunPaintFlags(0, paint.skPaint().getFlags());
if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) {
this->drawDFText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix,
@@ -304,6 +300,7 @@ GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
sk_sp<GrAtlasTextBlob> blob = blobCache->makeBlob(glyphCount, 1);
blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y());
+ blob->setRunPaintFlags(0, paint.skPaint().getFlags());
if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) {
this->drawDFPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix,
@@ -328,23 +325,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 +350,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 +377,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 +416,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 +439,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 +527,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 +736,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 +783,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 +818,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
diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h
index 36e83c4574..360f6ddbec 100644
--- a/src/gpu/text/GrAtlasTextContext.h
+++ b/src/gpu/text/GrAtlasTextContext.h
@@ -44,9 +44,6 @@ public:
static std::unique_ptr<GrAtlasTextContext> Make(const Options& options);
- bool canDraw(const GrAtlasGlyphCache* fontCache, const SkPaint&, const SkMatrix& viewMatrix,
- const SkSurfaceProps&, const GrShaderCaps&);
-
void drawText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
size_t byteLength, SkScalar x, SkScalar y, const SkIRect& regionClipBounds);
@@ -110,6 +107,16 @@ private:
int scalarsPerPosition, const SkPoint& offset,
SkScalar textRatio);
+ static void DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
+ const GrTextUtils::Paint& paint, const char text[],
+ size_t byteLength, SkScalar x, SkScalar y);
+
+ static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex,
+ const SkSurfaceProps& props, const GrTextUtils::Paint& paint,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], int scalarsPerPosition,
+ const SkPoint& offset, SkScalar textRatio);
+
// functions for appending distance field text
bool canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix,
const SkSurfaceProps& props, const GrShaderCaps& caps) const;
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index d354619a43..56c1d3309a 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -8,13 +8,10 @@
#include "GrTextUtils.h"
#include "GrContext.h"
#include "SkDrawFilter.h"
-#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkGr.h"
#include "SkPaint.h"
#include "SkTextBlobRunIterator.h"
-#include "SkTextMapStateProc.h"
-#include "SkTextToPathIter.h"
void GrTextUtils::Paint::initFilteredColor() {
// This mirrors the logic in skpaint_to_grpaint_impl for handling paint colors
@@ -35,7 +32,8 @@ void GrTextUtils::Paint::initFilteredColor() {
}
}
-bool GrTextUtils::RunPaint::modifyForRun(const SkTextBlobRunIterator& run) {
+
+bool GrTextUtils::RunPaint::modifyForRun(std::function<void(SkPaint*)> paintModFunc) {
if (!fModifiedPaint.isValid()) {
fModifiedPaint.init(fOriginalPaint->skPaint());
fPaint = fModifiedPaint.get();
@@ -44,7 +42,7 @@ bool GrTextUtils::RunPaint::modifyForRun(const SkTextBlobRunIterator& run) {
// changed the paint.
*fModifiedPaint.get() = fOriginalPaint->skPaint();
}
- run.applyFontToPaint(fModifiedPaint.get());
+ paintModFunc(fModifiedPaint.get());
if (fFilter) {
if (!fFilter->filter(fModifiedPaint.get(), SkDrawFilter::kText_Type)) {
@@ -77,82 +75,3 @@ bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) {
return paint.getMaskFilter() || paint.getPathEffect() ||
paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style;
}
-
-void GrTextUtils::DrawBigText(GrTextUtils::Target* target,
- const GrClip& clip, const SkPaint& paint,
- const SkMatrix& viewMatrix, const char text[], size_t byteLength,
- SkScalar x, SkScalar y, const SkIRect& clipBounds) {
- if (!paint.countText(text, byteLength)) {
- return;
- }
- SkTextToPathIter iter(text, byteLength, paint, true);
-
- SkMatrix matrix;
- matrix.setScale(iter.getPathScale(), iter.getPathScale());
- matrix.postTranslate(x, y);
-
- const SkPath* iterPath;
- SkScalar xpos, prevXPos = 0;
-
- while (iter.next(&iterPath, &xpos)) {
- matrix.postTranslate(xpos - prevXPos, 0);
- if (iterPath) {
- const SkPaint& pnt = iter.getPaint();
- target->drawPath(clip, *iterPath, pnt, viewMatrix, &matrix, clipBounds);
- }
- prevXPos = xpos;
- }
-}
-
-void GrTextUtils::DrawBigPosText(GrTextUtils::Target* target,
- const SkSurfaceProps& props, const GrClip& clip,
- const SkPaint& origPaint, const SkMatrix& viewMatrix,
- const char text[], size_t byteLength, const SkScalar pos[],
- int scalarsPerPosition, const SkPoint& offset,
- const SkIRect& clipBounds) {
- if (!origPaint.countText(text, byteLength)) {
- return;
- }
- // setup our std paint, in hopes of getting hits in the cache
- SkPaint paint(origPaint);
- SkScalar matrixScale = paint.setupForAsPaths();
-
- SkMatrix matrix;
- matrix.setScale(matrixScale, matrixScale);
-
- // 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);
-
- // Now restore the original settings, so we "draw" with whatever style/stroking.
- paint.setStyle(origPaint.getStyle());
- paint.setPathEffect(origPaint.refPathEffect());
-
- 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);
-
- matrix[SkMatrix::kMTransX] = loc.fX;
- matrix[SkMatrix::kMTransY] = loc.fY;
- target->drawPath(clip, *path, paint, viewMatrix, &matrix, clipBounds);
- }
- }
- pos += scalarsPerPosition;
- }
-}
diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h
index 252cd7c626..58318e8fe3 100644
--- a/src/gpu/text/GrTextUtils.h
+++ b/src/gpu/text/GrTextUtils.h
@@ -115,7 +115,7 @@ public:
fFilteredPremulColor = fOriginalPaint->filteredPremulColor();
}
- bool modifyForRun(const SkTextBlobRunIterator&);
+ bool modifyForRun(std::function<void(SkPaint*)> paintModFunc);
private:
SkTLazy<SkPaint> fModifiedPaint;
@@ -127,19 +127,6 @@ public:
static uint32_t FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint);
static bool ShouldDisableLCD(const SkPaint& paint);
-
- // Functions for drawing large text either as paths or (for color emoji) as scaled glyphs
- static void DrawBigText(GrTextUtils::Target*, const GrClip& clip,
- const SkPaint& paint, const SkMatrix& viewMatrix, const char text[],
- size_t byteLength, SkScalar x, SkScalar y,
- const SkIRect& clipBounds);
-
- static void DrawBigPosText(GrTextUtils::Target*,
- const SkSurfaceProps& props, const GrClip& clip,
- const SkPaint& paint, const SkMatrix& viewMatrix,
- const char text[], size_t byteLength, const SkScalar pos[],
- int scalarsPerPosition, const SkPoint& offset,
- const SkIRect& clipBounds);
};
#endif