aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/SkCanvas_Reference.bmh3
-rw-r--r--gm/drawatlas.cpp8
-rw-r--r--include/core/SkCanvas.h3
-rw-r--r--src/core/SkDevice.cpp15
4 files changed, 26 insertions, 3 deletions
diff --git a/docs/SkCanvas_Reference.bmh b/docs/SkCanvas_Reference.bmh
index 1db1d0f077..a43b5fc172 100644
--- a/docs/SkCanvas_Reference.bmh
+++ b/docs/SkCanvas_Reference.bmh
@@ -5064,7 +5064,8 @@ void draw(SkCanvas* canvas) {
#In Draw
#Line # draws null terminated string at (x, y) using font advance ##
Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
-Paint paint.
+Paint paint. Note that this per-glyph xform does not affect the shader (if present)
+on the paint, just the glyph's geometry.
string meaning depends on Paint_Text_Encoding; by default, strings are encoded
as UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
diff --git a/gm/drawatlas.cpp b/gm/drawatlas.cpp
index be939c7505..9608ddf58d 100644
--- a/gm/drawatlas.cpp
+++ b/gm/drawatlas.cpp
@@ -150,12 +150,20 @@ static void draw_text_on_path(SkCanvas* canvas, const void* text, size_t length,
}
}
+#include "SkGradientShader.h"
+static sk_sp<SkShader> make_shader() {
+ SkPoint pts[2] = {{0, 0}, {220, 0}};
+ SkColor colors[2] = {SK_ColorRED, SK_ColorBLUE};
+ return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kMirror_TileMode);
+}
+
static void drawTextPath(SkCanvas* canvas, bool useRSX, bool doStroke) {
const char text0[] = "ABCDFGHJKLMNOPQRSTUVWXYZ";
const int N = sizeof(text0) - 1;
SkPoint pos[N];
SkPaint paint;
+ paint.setShader(make_shader());
paint.setAntiAlias(true);
paint.setTextSize(100);
if (doStroke) {
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 8c86cd2f13..a426d1e546 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -2055,7 +2055,8 @@ public:
using clip, SkMatrix, and SkPaint paint.
SkRSXform array specifies a separate square scale, rotation, and translation for
- each glyph.
+ each glyph. Note that this per-glyph xform does not affect the shader (if present)
+ on the paint, just the glyph's geometry.
Optional SkRect cullRect is a conservative bounds of text, taking into account
SkRSXform and paint. If cullRect is outside of clip, canvas can skip drawing.
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index e404d16c8d..210af808c9 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -14,6 +14,7 @@
#include "SkImagePriv.h"
#include "SkImage_Base.h"
#include "SkLatticeIter.h"
+#include "SkLocalMatrixShader.h"
#include "SkMatrixPriv.h"
#include "SkPatchUtils.h"
#include "SkPathMeasure.h"
@@ -495,6 +496,9 @@ void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
break;
}
+ SkPaint localPaint(paint);
+ SkShader* shader = paint.getShader();
+
SkMatrix localM, currM;
const void* stopText = (const char*)text + len;
while ((const char*)text < (const char*)stopText) {
@@ -502,8 +506,17 @@ void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
currM.setConcat(this->ctm(), localM);
SkAutoDeviceCTMRestore adc(this, currM);
+ // We want to rotate each glyph by the rsxform, but we don't want to rotate "space"
+ // (i.e. the shader that cares about the ctm) so we have to undo our little ctm trick
+ // with a localmatrixshader so that the shader draws as if there was no change to the ctm.
+ if (shader) {
+ SkMatrix inverse;
+ SkAssertResult(localM.invert(&inverse));
+ localPaint.setShader(shader->makeWithLocalMatrix(inverse));
+ }
+
int subLen = proc((const char*)text);
- this->drawText(text, subLen, 0, 0, paint);
+ this->drawText(text, subLen, 0, 0, localPaint);
text = (const char*)text + subLen;
}
}