diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp index 31897436d2..9ae21c01a5 100644 --- a/src/core/SkGlyphRun.cpp +++ b/src/core/SkGlyphRun.cpp @@ -104,6 +104,15 @@ bool SkGlyphRunList::anyRunsLCD() const { return false; } +bool SkGlyphRunList::anyRunsSubpixelPositioned() const { + for (const auto& r : fGlyphRuns) { + if (r.paint().isSubpixelText()) { + return true; + } + } + return false; +} + void SkGlyphRunList::temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const { SkASSERT(fOriginalTextBlob != nullptr); fOriginalTextBlob->notifyAddedToCache(cacheID); diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h index 3f7c26eb0d..2d0d345523 100644 --- a/src/core/SkGlyphRun.h +++ b/src/core/SkGlyphRun.h @@ -151,6 +151,7 @@ public: uint64_t uniqueID() const; bool anyRunsLCD() const; + bool anyRunsSubpixelPositioned() const; void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const; bool canCache() const { return fOriginalTextBlob != nullptr; } diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp index 1d4d7daf73..cfaafe35aa 100644 --- a/src/core/SkGlyphRunPainter.cpp +++ b/src/core/SkGlyphRunPainter.cpp @@ -388,7 +388,8 @@ void GrTextContext::drawGlyphRunList( } if (cacheBlob) { - if (cacheBlob->mustRegenerate(listPaint, blurRec, viewMatrix, origin.x(), origin.y())) { + if (cacheBlob->mustRegenerate(listPaint, glyphRunList.anyRunsSubpixelPositioned(), + blurRec, viewMatrix, origin.x(),origin.y())) { // We have to remake the blob because changes may invalidate our masks. // TODO we could probably get away reuse most of the time if the pointer is unique, // but we'd have to clear the subrun information diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp index 659a545455..6249c3a48f 100644 --- a/src/gpu/text/GrTextBlob.cpp +++ b/src/gpu/text/GrTextBlob.cpp @@ -144,9 +144,9 @@ void GrTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, S run.fPathGlyphs.push_back(GrTextBlob::Run::PathGlyph(path, x, y, scale, preTransformed)); } -bool GrTextBlob::mustRegenerate(const SkPaint& paint, - const SkMaskFilterBase::BlurRec& blurRec, - const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { +bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosition, + const SkMaskFilterBase::BlurRec& blurRec, + const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { // If we have LCD text then our canonical color will be set to transparent, in this case we have // to regenerate the blob on any color change // We use the grPaint to get any color filter effects @@ -196,20 +196,22 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, return true; } - // We can update the positions in the cachedtextblobs without regenerating the whole blob, - // but only for integer translations. - // This cool bit of math will determine the necessary translation to apply to the already - // generated vertex coordinates to move them to the correct position - SkScalar transX = viewMatrix.getTranslateX() + - viewMatrix.getScaleX() * (x - fInitialX) + - viewMatrix.getSkewX() * (y - fInitialY) - - fInitialViewMatrix.getTranslateX(); - SkScalar transY = viewMatrix.getTranslateY() + - viewMatrix.getSkewY() * (x - fInitialX) + - viewMatrix.getScaleY() * (y - fInitialY) - - fInitialViewMatrix.getTranslateY(); - if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) { - return true; + if (!anyRunHasSubpixelPosition) { + // We can update the positions in the cachedtextblobs without regenerating the whole + // blob, but only for integer translations. + // This cool bit of math will determine the necessary translation to apply to the + // already generated vertex coordinates to move them to the correct position. + SkScalar transX = viewMatrix.getTranslateX() + + viewMatrix.getScaleX() * (x - fInitialX) + + viewMatrix.getSkewX() * (y - fInitialY) - + fInitialViewMatrix.getTranslateX(); + SkScalar transY = viewMatrix.getTranslateY() + + viewMatrix.getSkewY() * (x - fInitialX) + + viewMatrix.getScaleY() * (y - fInitialY) - + fInitialViewMatrix.getTranslateY(); + if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) { + return true; + } } } else if (this->hasDistanceField()) { // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h index f8a45659e1..234039fb6a 100644 --- a/src/gpu/text/GrTextBlob.h +++ b/src/gpu/text/GrTextBlob.h @@ -196,7 +196,7 @@ public: } } - bool mustRegenerate(const SkPaint&, const SkMaskFilterBase::BlurRec& blurRec, + bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec, const SkMatrix& viewMatrix, SkScalar x, SkScalar y); void flush(GrTextTarget*, const SkSurfaceProps& props,