Redo GrTextBlob path flush
Change-Id: I4cd27b5367983d70d5c18383e21ae918b0dd8f45
Reviewed-on: https://skia-review.googlesource.com/156981
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 3e6b327..659a545 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -290,54 +290,88 @@
// GrTextBlob::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;
- SkPaint runPaint{paint};
+ // For each run in the GrTextBlob we're going to churn through all the glyphs.
+ // Each run is broken into a path part and a Mask / DFT / ARGB part.
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;
- runPaint.setFlags((runPaint.getFlags() & ~Run::kPaintFlagsMask) | paintFlags);
+ SkPaint runPaint{paint};
+ runPaint.setFlags((runPaint.getFlags() & ~Run::kPaintFlagsMask) | run.fPaintFlags);
for (int i = 0; i < run.fPathGlyphs.count(); i++) {
GrTextBlob::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);
-
+ SkMatrix ctm;
const SkPath* path = &pathGlyph.fPath;
+
+ // TmpPath must be in the same scope as GrShape shape below.
SkTLazy<SkPath> tmpPath;
- GrStyle style(runPaint);
+ // The glyph positions and glyph outlines are either in device space or in source
+ // space based on fPreTransformed.
+ if (!pathGlyph.fPreTransformed) {
+ // Positions and outlines are in source space.
- SkMaskFilter* mf = runPaint.getMaskFilter();
+ ctm = viewMatrix;
- // Styling, blurs, and shading are supposed to be applied *after* the pathMatrix.
- // However, if the mask filter is a blur and the pathMatrix contains no scale, then
- // we can still fold the path matrix into the CTM
- bool needToApply = runPaint.getShader() || style.applies() ||
- (mf && (!as_MFB(mf)->asABlur(nullptr) ||
- !SkScalarNearlyEqual(pathGlyph.fScale, 1.0f)));
+ SkMatrix pathMatrix = SkMatrix::MakeScale(pathGlyph.fScale, pathGlyph.fScale);
- if (needToApply) {
- SkPath* result = tmpPath.init();
- path->transform(pathMatrix, result);
- result->setIsVolatile(true);
- path = result;
+ // The origin for the blob may have changed, so figure out the delta.
+ SkVector originShift = SkPoint{x, y} - SkPoint{fInitialX, fInitialY};
+
+ // Shift the original glyph location in source space to the position of the new
+ // blob.
+ pathMatrix.postTranslate(originShift.x() + pathGlyph.fX,
+ originShift.y() + pathGlyph.fY);
+
+ // If there are shaders, blurs or styles, the path must be scaled into source
+ // space independently of the CTM. This allows the CTM to be correct for the
+ // different effects.
+ GrStyle style(runPaint);
+ bool scalePath = runPaint.getShader()
+ || style.applies()
+ || runPaint.getMaskFilter();
+ if (!scalePath) {
+ // Scale can be applied to CTM -- no effects.
+
+ ctm.preConcat(pathMatrix);
+ } else {
+ // Scale the outline into source space.
+
+ // Transform the path form the normalized outline to source space. This
+ // way the CTM will remain the same so it can be used by the effects.
+ SkPath* sourceOutline = tmpPath.init();
+ path->transform(pathMatrix, sourceOutline);
+ sourceOutline->setIsVolatile(true);
+ path = sourceOutline;
+ }
+
+
} else {
- pathMatrix.postConcat(*ctm);
- ctm = &pathMatrix;
+ // Positions and outlines are in device space.
+
+ SkPoint originalOrigin = {fInitialX, fInitialY};
+ fInitialViewMatrix.mapPoints(&originalOrigin, 1);
+
+ SkPoint newOrigin = {x, y};
+ viewMatrix.mapPoints(&newOrigin, 1);
+
+ // The origin shift in device space.
+ SkPoint originShift = newOrigin - originalOrigin;
+
+ // Shift the original glyph location in device space to the position of the
+ // new blob.
+ ctm = SkMatrix::MakeTrans(originShift.x() + pathGlyph.fX,
+ originShift.y() + pathGlyph.fY);
}
// TODO: we are losing the mutability of the path here
GrShape shape(*path, paint);
- target->drawShape(clip, runPaint, *ctm, shape);
+ target->drawShape(clip, runPaint, ctm, shape);
}
}
@@ -345,6 +379,7 @@
if (!run.fInitialized) {
continue;
}
+
int lastSubRun = SkTMin(run.fSubRunInfo.count(), 1 << 16) - 1;
for (int subRun = 0; subRun <= lastSubRun; subRun++) {
const Run::SubRunInfo& info = run.fSubRunInfo[subRun];