aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/drawatlas.cpp65
-rw-r--r--include/core/SkCanvas.h10
-rw-r--r--include/core/SkDevice.h2
-rw-r--r--include/core/SkPicture.h3
-rw-r--r--include/private/SkRecords.h7
-rw-r--r--include/utils/SkDumpCanvas.h2
-rw-r--r--include/utils/SkLuaCanvas.h2
-rw-r--r--include/utils/SkNWayCanvas.h2
-rw-r--r--include/utils/SkPaintFilterCanvas.h2
-rw-r--r--src/core/SkCanvas.cpp22
-rw-r--r--src/core/SkDevice.cpp41
-rw-r--r--src/core/SkPictureFlat.h5
-rw-r--r--src/core/SkPicturePlayback.cpp13
-rw-r--r--src/core/SkPictureRecord.cpp24
-rw-r--r--src/core/SkPictureRecord.h2
-rw-r--r--src/core/SkRecordDraw.cpp11
-rw-r--r--src/core/SkRecorder.cpp10
-rw-r--r--src/core/SkRecorder.h5
-rw-r--r--src/utils/SkDumpCanvas.cpp8
-rw-r--r--src/utils/SkLuaCanvas.cpp8
-rw-r--r--src/utils/SkNWayCanvas.cpp8
-rw-r--r--src/utils/SkPaintFilterCanvas.cpp9
-rw-r--r--tools/android/SkAndroidSDKCanvas.cpp14
-rw-r--r--tools/android/SkAndroidSDKCanvas.h2
-rw-r--r--tools/debugger/SkDebugCanvas.cpp5
-rw-r--r--tools/debugger/SkDebugCanvas.h2
-rw-r--r--tools/debugger/SkDrawCommand.cpp60
-rw-r--r--tools/debugger/SkDrawCommand.h22
28 files changed, 361 insertions, 5 deletions
diff --git a/gm/drawatlas.cpp b/gm/drawatlas.cpp
index a906cbedeb..ba71eaea57 100644
--- a/gm/drawatlas.cpp
+++ b/gm/drawatlas.cpp
@@ -100,3 +100,68 @@ private:
typedef GM INHERITED;
};
DEF_GM( return new DrawAtlasGM; )
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+#include "SkPath.h"
+#include "SkPathMeasure.h"
+
+static void draw_text_on_path_rigid(SkCanvas* canvas, const void* text, size_t length,
+ const SkPoint xy[], const SkPath& path, const SkPaint& paint) {
+ SkPathMeasure meas(path, false);
+
+ int count = paint.countText(text, length);
+ SkAutoSTArray<100, SkRSXform> xform(count);
+
+ for (int i = 0; i < count; ++i) {
+ SkPoint pos;
+ SkVector tan;
+ if (!meas.getPosTan(xy[i].x(), &pos, &tan)) {
+ pos = xy[i];
+ tan.set(1, 0);
+ }
+ xform[i].fSCos = tan.x();
+ xform[i].fSSin = tan.y();
+ xform[i].fTx = pos.x();
+ xform[i].fTy = pos.y();
+ }
+
+ canvas->drawTextRSXform(text, length, &xform[0], nullptr, paint);
+}
+
+DEF_SIMPLE_GM(drawTextRSXform, canvas, 510, 310) {
+ const char text[] = "ABCDFGHJKLMNOPQRSTUVWXYZ";
+ const int N = sizeof(text) - 1;
+ SkPoint pos[N];
+ SkRSXform xform[N];
+
+ canvas->translate(0, 30);
+
+ SkScalar x = 20;
+ SkScalar dx = 20;
+ SkScalar rad = 0;
+ SkScalar drad = 2 * SK_ScalarPI / (N - 1);
+ for (int i = 0; i < N; ++i) {
+ xform[i].fSCos = SkScalarCos(rad);
+ xform[i].fSSin = SkScalarSin(rad);
+ xform[i].fTx = x;
+ xform[i].fTy = 0;
+ pos[i].set(x, 0);
+ x += dx;
+ rad += drad;
+ }
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(20);
+ canvas->drawTextRSXform(text, N, xform, nullptr, paint);
+
+ SkPath path;
+ path.addOval(SkRect::MakeXYWH(150, 50, 200, 200));
+
+ draw_text_on_path_rigid(canvas, text, N, pos, path, paint);
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+}
+
+
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index ec14829ca8..7dd0189441 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -989,6 +989,14 @@ public:
void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint& paint);
+ /**
+ * Draw the text with each character/glyph individually transformed by its xform.
+ * If cullRect is not null, it is a conservative bounds of what will be drawn
+ * taking into account the xforms and the paint) and will be used to accelerate culling.
+ */
+ void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
+ const SkRect* cullRect, const SkPaint& paint);
+
/** Draw the text blob, offset by (x,y), using the specified paint.
@param blob The text blob to be drawn
@param x The x-offset of the text being drawn
@@ -1324,6 +1332,8 @@ protected:
virtual void onDrawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint);
+ virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
+ const SkRect* cullRect, const SkPaint& paint);
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint);
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index e06650036d..d23aa6916f 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -273,6 +273,8 @@ protected:
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath&,
const SkMatrix*, const SkPaint&);
+ virtual void drawTextRSXform(const SkDraw&, const void* text, size_t len, const SkRSXform[],
+ const SkPaint&);
bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index eb35ef6366..8e3d1c8019 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -206,10 +206,11 @@ private:
// V43: Added DRAW_IMAGE and DRAW_IMAGE_RECT opt codes to serialized data
// V44: Move annotations from paint to drawAnnotation
// V45: Add invNormRotation to SkLightingShader.
+ // V46: Add drawTextRSXform
// Only SKPs within the min/current picture version range (inclusive) can be read.
static const uint32_t MIN_PICTURE_VERSION = 35; // Produced by Chrome M39.
- static const uint32_t CURRENT_PICTURE_VERSION = 45;
+ static const uint32_t CURRENT_PICTURE_VERSION = 46;
static_assert(MIN_PICTURE_VERSION <= 41,
"Remove kFontFileName and related code from SkFontDescriptor.cpp.");
diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h
index d6ef12fe6c..9ec2d2116c 100644
--- a/include/private/SkRecords.h
+++ b/include/private/SkRecords.h
@@ -72,6 +72,7 @@ namespace SkRecords {
M(DrawPosTextH) \
M(DrawText) \
M(DrawTextOnPath) \
+ M(DrawTextRSXform) \
M(DrawRRect) \
M(DrawRect) \
M(DrawTextBlob) \
@@ -344,6 +345,12 @@ RECORD(DrawTextOnPath, kDraw_Tag|kHasText_Tag,
size_t byteLength;
PreCachedPath path;
TypedMatrix matrix);
+RECORD(DrawTextRSXform, kDraw_Tag|kHasText_Tag,
+ SkPaint paint;
+ PODArray<char> text;
+ size_t byteLength;
+ PODArray<SkRSXform> xforms;
+ Optional<SkRect> cull);
RECORD(DrawPatch, kDraw_Tag,
SkPaint paint;
PODArray<SkPoint> cubics;
diff --git a/include/utils/SkDumpCanvas.h b/include/utils/SkDumpCanvas.h
index 35d694eedb..fc058be657 100644
--- a/include/utils/SkDumpCanvas.h
+++ b/include/utils/SkDumpCanvas.h
@@ -87,6 +87,8 @@ protected:
SkScalar constY, const SkPaint&) override;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) override;
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
diff --git a/include/utils/SkLuaCanvas.h b/include/utils/SkLuaCanvas.h
index 37e82be51d..64f285b26c 100644
--- a/include/utils/SkLuaCanvas.h
+++ b/include/utils/SkLuaCanvas.h
@@ -37,6 +37,8 @@ protected:
SkScalar constY, const SkPaint&) override;
virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) override;
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h
index f2a99db802..a4b9c59412 100644
--- a/include/utils/SkNWayCanvas.h
+++ b/include/utils/SkNWayCanvas.h
@@ -49,6 +49,8 @@ protected:
const SkMatrix* matrix, const SkPaint&) override;
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) override;
virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkXfermode* xmode,
const SkPaint& paint) override;
diff --git a/include/utils/SkPaintFilterCanvas.h b/include/utils/SkPaintFilterCanvas.h
index 909cf3b987..037bac6f73 100644
--- a/include/utils/SkPaintFilterCanvas.h
+++ b/include/utils/SkPaintFilterCanvas.h
@@ -95,6 +95,8 @@ protected:
SkScalar constY, const SkPaint&) override;
void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) override;
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index ce90275047..733ff19f91 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2647,6 +2647,21 @@ void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPat
LOOPER_END
}
+void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cullRect, const SkPaint& paint) {
+ if (cullRect && this->quickReject(*cullRect)) {
+ return;
+ }
+
+ LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
+
+ while (iter.next()) {
+ iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint());
+ }
+
+ LOOPER_END
+}
+
void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
@@ -2699,6 +2714,13 @@ void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath&
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
}
+void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cullRect, const SkPaint& paint) {
+ TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
+ if (byteLength) {
+ this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
+ }
+}
void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
RETURN_ON_NULL(blob);
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 185b9bbd27..2dcedb4bd7 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -403,6 +403,47 @@ void SkBaseDevice::drawTextOnPath(const SkDraw& draw, const void* text, size_t b
}
}
+#include "SkUtils.h"
+typedef int (*CountTextProc)(const char* text);
+static int count_utf16(const char* text) {
+ const uint16_t* prev = (uint16_t*)text;
+ (void)SkUTF16_NextUnichar(&prev);
+ return SkToInt((const char*)prev - text);
+}
+static int return_4(const char* text) { return 4; }
+static int return_2(const char* text) { return 2; }
+
+void SkBaseDevice::drawTextRSXform(const SkDraw& draw, const void* text, size_t len,
+ const SkRSXform xform[], const SkPaint& paint) {
+ CountTextProc proc = nullptr;
+ switch (paint.getTextEncoding()) {
+ case SkPaint::kUTF8_TextEncoding:
+ proc = SkUTF8_CountUTF8Bytes;
+ break;
+ case SkPaint::kUTF16_TextEncoding:
+ proc = count_utf16;
+ break;
+ case SkPaint::kUTF32_TextEncoding:
+ proc = return_4;
+ break;
+ case SkPaint::kGlyphID_TextEncoding:
+ proc = return_2;
+ break;
+ }
+
+ SkDraw localD(draw);
+ SkMatrix localM, currM;
+ const void* stopText = (const char*)text + len;
+ while ((const char*)text < (const char*)stopText) {
+ localM.setRSXform(*xform++);
+ currM.setConcat(*draw.fMatrix, localM);
+ localD.fMatrix = &currM;
+ int subLen = proc((const char*)text);
+ this->drawText(localD, text, subLen, 0, 0, paint);
+ text = (const char*)text + subLen;
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
void SkBaseDevice::drawSpriteWithFilter(const SkDraw& draw, const SkBitmap& bitmap,
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index d4c8c1f365..3546fb2e0a 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -79,6 +79,7 @@ enum DrawType {
DRAW_ANNOTATION,
DRAW_DRAWABLE,
DRAW_DRAWABLE_MATRIX,
+ DRAW_TEXT_RSXFORM,
LAST_DRAWTYPE_ENUM = DRAW_DRAWABLE_MATRIX,
};
@@ -98,6 +99,10 @@ enum DrawAtlasFlags {
DRAW_ATLAS_HAS_CULL = 1 << 1,
};
+enum DrawTextRSXformFlags {
+ DRAW_TEXT_RSXFORM_HAS_CULL = 1 << 0,
+};
+
enum SaveLayerRecFlatFlags {
SAVELAYERREC_HAS_BOUNDS = 1 << 0,
SAVELAYERREC_HAS_PAINT = 1 << 1,
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 3cbcdbbd2f..6b8930436f 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -501,6 +501,19 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint);
}
} break;
+ case DRAW_TEXT_RSXFORM: {
+ const SkPaint* paint = fPictureData->getPaint(reader);
+ int count = reader->readInt();
+ uint32_t flags = reader->read32();
+ TextContainer text;
+ get_text(reader, &text);
+ const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
+ const SkRect* cull = nullptr;
+ if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
+ cull = (const SkRect*)reader->skip(sizeof(SkRect));
+ }
+ canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint);
+ } break;
case DRAW_VERTICES: {
sk_sp<SkXfermode> xfer;
const SkPaint* paint = fPictureData->getPaint(reader);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 4a6ece17f2..17ed1aa20b 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -603,6 +603,30 @@ void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, cons
this->validate(initialOffset, size);
}
+void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
+ const SkRSXform xform[], const SkRect* cull,
+ const SkPaint& paint) {
+ const int count = paint.countText(text, byteLength);
+ // [op + paint-index + count + flags + length] + [text] + [xform] + cull
+ size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
+ uint32_t flags = 0;
+ if (cull) {
+ flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
+ size += sizeof(SkRect);
+ }
+
+ size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
+ this->addPaint(paint);
+ this->addInt(count);
+ this->addInt(flags);
+ this->addText(text, byteLength);
+ fWriter.write(xform, count * sizeof(SkRSXform));
+ if (cull) {
+ fWriter.write(cull, sizeof(SkRect));
+ }
+ this->validate(initialOffset, size);
+}
+
void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 8504c00ee4..bdb6609bd9 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -167,6 +167,8 @@ protected:
const SkPaint&) override;
void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint&) override;
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index d0e8c4cf48..ec9aee9562 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -114,6 +114,7 @@ DRAW(DrawRect, drawRect(r.rect, r.paint));
DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint));
DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.paint));
+DRAW(DrawTextRSXform, drawTextRSXform(r.text, r.byteLength, r.xforms, r.cull, r.paint));
DRAW(DrawAtlas, drawAtlas(r.atlas, r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint));
DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
r.xmode, r.indices, r.indexCount, r.paint));
@@ -454,6 +455,8 @@ private:
Bounds bounds(const DrawAtlas& op) const {
if (op.cull) {
+ // TODO: <reed> can we pass nullptr for the paint? Isn't cull already "correct"
+ // for the paint (by the caller)?
return this->adjustAndMap(*op.cull, op.paint);
} else {
return fCurrentClipBounds;
@@ -508,6 +511,14 @@ private:
return this->adjustAndMap(dst, &op.paint);
}
+ Bounds bounds(const DrawTextRSXform& op) const {
+ if (op.cull) {
+ return this->adjustAndMap(*op.cull, nullptr);
+ } else {
+ return fCurrentClipBounds;
+ }
+ }
+
Bounds bounds(const DrawTextBlob& op) const {
SkRect dst = op.blob->bounds();
dst.offset(op.x, op.y);
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index ff5c27d7e5..19cb663eaf 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -278,6 +278,16 @@ void SkRecorder::onDrawTextOnPath(const void* text, size_t byteLength, const SkP
matrix ? *matrix : SkMatrix::I());
}
+void SkRecorder::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) {
+ APPEND(DrawTextRSXform,
+ paint,
+ this->copy((const char*)text, byteLength),
+ byteLength,
+ this->copy(xform, paint.countText(text, byteLength)),
+ this->copy(cull));
+}
+
void SkRecorder::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
TRY_MINIRECORDER(drawTextBlob, blob, x, y, paint);
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 1299efbdd6..3cf0be97c3 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -82,6 +82,11 @@ public:
const SkPath& path,
const SkMatrix* matrix,
const SkPaint& paint) override;
+ void onDrawTextRSXform(const void* text,
+ size_t byteLength,
+ const SkRSXform[],
+ const SkRect* cull,
+ const SkPaint& paint) override;
void onDrawTextBlob(const SkTextBlob* blob,
SkScalar x,
SkScalar y,
diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp
index 7a37fcb5c1..5166640ca6 100644
--- a/src/utils/SkDumpCanvas.cpp
+++ b/src/utils/SkDumpCanvas.cpp
@@ -429,6 +429,14 @@ void SkDumpCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const S
str.c_str(), byteLength);
}
+void SkDumpCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) {
+ SkString str;
+ toString(text, byteLength, paint.getTextEncoding(), &str);
+ this->dump(kDrawText_Verb, &paint, "drawTextRSXform(%s [%d])",
+ str.c_str(), byteLength);
+}
+
void SkDumpCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
SkString str;
diff --git a/src/utils/SkLuaCanvas.cpp b/src/utils/SkLuaCanvas.cpp
index c51b0d8a7c..a3160af800 100644
--- a/src/utils/SkLuaCanvas.cpp
+++ b/src/utils/SkLuaCanvas.cpp
@@ -273,6 +273,14 @@ void SkLuaCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const Sk
lua.pushPaint(paint, "paint");
}
+void SkLuaCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) {
+ AUTO_LUA("drawTextRSXform");
+ lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
+ // TODO: export other params
+ lua.pushPaint(paint, "paint");
+}
+
void SkLuaCanvas::onDrawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y,
const SkPaint &paint) {
AUTO_LUA("drawTextBlob");
diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp
index 4397814d04..dc9437c404 100644
--- a/src/utils/SkNWayCanvas.cpp
+++ b/src/utils/SkNWayCanvas.cpp
@@ -254,6 +254,14 @@ void SkNWayCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const S
}
}
+void SkNWayCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawTextRSXform(text, byteLength, xform, cull, paint);
+ }
+}
+
void SkNWayCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint &paint) {
Iter iter(fList);
diff --git a/src/utils/SkPaintFilterCanvas.cpp b/src/utils/SkPaintFilterCanvas.cpp
index ea94068cb6..75a7930500 100644
--- a/src/utils/SkPaintFilterCanvas.cpp
+++ b/src/utils/SkPaintFilterCanvas.cpp
@@ -204,6 +204,15 @@ void SkPaintFilterCanvas::onDrawTextOnPath(const void* text, size_t byteLength,
}
}
+void SkPaintFilterCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
+ const SkRSXform xform[], const SkRect* cull,
+ const SkPaint& paint) {
+ AutoPaintFilter apf(this, kText_Type, paint);
+ if (apf.shouldDraw()) {
+ this->INHERITED::onDrawTextRSXform(text, byteLength, xform, cull, *apf.paint());
+ }
+}
+
void SkPaintFilterCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
AutoPaintFilter apf(this, kTextBlob_Type, paint);
diff --git a/tools/android/SkAndroidSDKCanvas.cpp b/tools/android/SkAndroidSDKCanvas.cpp
index c1a40f4766..8d95d8a1b0 100644
--- a/tools/android/SkAndroidSDKCanvas.cpp
+++ b/tools/android/SkAndroidSDKCanvas.cpp
@@ -200,13 +200,19 @@ void SkAndroidSDKCanvas::onDrawPosTextH(const void* text,
fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint);
}
void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text,
- size_t byteLength,
- const SkPath& path,
- const SkMatrix* matrix,
- const SkPaint& paint) {
+ size_t byteLength,
+ const SkPath& path,
+ const SkMatrix* matrix,
+ const SkPaint& paint) {
FILTER(paint);
fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint);
}
+void SkAndroidSDKCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
+ const SkRSXform xform[], const SkRect* cull,
+ const SkPaint& paint) {
+ FILTER(paint);
+ fProxyTarget->drawTextRSXform(text, byteLength, xform, cull, filteredPaint);
+}
void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob,
SkScalar x,
SkScalar y,
diff --git a/tools/android/SkAndroidSDKCanvas.h b/tools/android/SkAndroidSDKCanvas.h
index 78cfa93dcd..b7be797b84 100644
--- a/tools/android/SkAndroidSDKCanvas.h
+++ b/tools/android/SkAndroidSDKCanvas.h
@@ -62,6 +62,8 @@ protected:
SkScalar constY, const SkPaint& paint) override;
void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint& paint) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) override;
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
diff --git a/tools/debugger/SkDebugCanvas.cpp b/tools/debugger/SkDebugCanvas.cpp
index ceea782193..b80eeea0b1 100644
--- a/tools/debugger/SkDebugCanvas.cpp
+++ b/tools/debugger/SkDebugCanvas.cpp
@@ -644,6 +644,11 @@ void SkDebugCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const
new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
}
+void SkDebugCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+ const SkRect* cull, const SkPaint& paint) {
+ this->addDrawCommand(new SkDrawTextRSXformCommand(text, byteLength, xform, cull, paint));
+}
+
void SkDebugCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
this->addDrawCommand(new SkDrawTextBlobCommand(blob, x, y, paint));
diff --git a/tools/debugger/SkDebugCanvas.h b/tools/debugger/SkDebugCanvas.h
index d0cdf82a36..e8d9113438 100644
--- a/tools/debugger/SkDebugCanvas.h
+++ b/tools/debugger/SkDebugCanvas.h
@@ -204,6 +204,8 @@ protected:
SkScalar constY, const SkPaint&) override;
void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint&) override;
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[], const SkRect*,
+ const SkPaint&) override;
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index 6c9287fa31..d58b3c935e 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -204,6 +204,7 @@ const char* SkDrawCommand::GetCommandString(OpType type) {
case kDrawText_OpType: return "DrawText";
case kDrawTextBlob_OpType: return "DrawTextBlob";
case kDrawTextOnPath_OpType: return "DrawTextOnPath";
+ case kDrawTextRSXform_OpType: return "drawTextRSXform";
case kDrawVertices_OpType: return "DrawVertices";
case kEndDrawPicture_OpType: return "EndDrawPicture";
case kRestore_OpType: return "Restore";
@@ -257,6 +258,7 @@ SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& url
INSTALL_FACTORY(DrawPosText);
INSTALL_FACTORY(DrawPosTextH);
INSTALL_FACTORY(DrawTextOnPath);
+ INSTALL_FACTORY(DrawTextRSXform);
INSTALL_FACTORY(DrawTextBlob);
INSTALL_FACTORY(DrawRect);
@@ -2956,6 +2958,8 @@ SkDrawTextCommand* SkDrawTextCommand::fromJSON(Json::Value& command,
paint);
}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint)
@@ -3017,6 +3021,62 @@ SkDrawTextOnPathCommand* SkDrawTextOnPathCommand::fromJSON(Json::Value& command,
return new SkDrawTextOnPathCommand(text, strlen(text), path, matrixPtr, paint);
}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SkDrawTextRSXformCommand::SkDrawTextRSXformCommand(const void* text, size_t byteLength,
+ const SkRSXform xform[], const SkRect* cull,
+ const SkPaint& paint)
+ : INHERITED(kDrawTextOnPath_OpType)
+{
+ fText = new char[byteLength];
+ memcpy(fText, text, byteLength);
+ fByteLength = byteLength;
+ int count = paint.countText(text, byteLength);
+ fXform = new SkRSXform[count];
+ memcpy(fXform, xform, count * sizeof(SkRSXform));
+ if (cull) {
+ fCullStorage = *cull;
+ fCull = &fCullStorage;
+ } else {
+ fCull = nullptr;
+ }
+ fPaint = paint;
+
+ fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
+ fInfo.push(SkObjectParser::PaintToString(paint));
+}
+
+void SkDrawTextRSXformCommand::execute(SkCanvas* canvas) const {
+ canvas->drawTextRSXform(fText, fByteLength, fXform, fCull, fPaint);
+}
+
+Json::Value SkDrawTextRSXformCommand::toJSON(UrlDataManager& urlDataManager) const {
+ Json::Value result = INHERITED::toJSON(urlDataManager);
+ result[SKDEBUGCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) fText,
+ ((const char*) fText) + fByteLength);
+ result[SKDEBUGCANVAS_ATTRIBUTE_PAINT] = MakeJsonPaint(fPaint, urlDataManager);
+ return result;
+}
+
+SkDrawTextRSXformCommand* SkDrawTextRSXformCommand::fromJSON(Json::Value& command,
+ UrlDataManager& urlDataManager) {
+ const char* text = command[SKDEBUGCANVAS_ATTRIBUTE_TEXT].asCString();
+ size_t byteLength = strlen(text);
+ SkPaint paint;
+ extract_json_paint(command[SKDEBUGCANVAS_ATTRIBUTE_PAINT], urlDataManager, &paint);
+
+ // TODO: handle xform and cull
+ int count = paint.countText(text, byteLength);
+ SkAutoTArray<SkRSXform> xform(count);
+ for (int i = 0; i < count; ++i) {
+ xform[i].fSCos = 1;
+ xform[i].fSSin = xform[i].fTx = xform[i].fTy = 0;
+ }
+ return new SkDrawTextRSXformCommand(text, byteLength, &xform[0], nullptr, paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xfermode,
diff --git a/tools/debugger/SkDrawCommand.h b/tools/debugger/SkDrawCommand.h
index 8b8ada267f..dc639ec3a3 100644
--- a/tools/debugger/SkDrawCommand.h
+++ b/tools/debugger/SkDrawCommand.h
@@ -14,6 +14,7 @@
#include "SkTLazy.h"
#include "SkPath.h"
#include "SkRRect.h"
+#include "SkRSXform.h"
#include "SkString.h"
#include "SkTDArray.h"
#include "SkJSONCPP.h"
@@ -48,6 +49,7 @@ public:
kDrawText_OpType,
kDrawTextBlob_OpType,
kDrawTextOnPath_OpType,
+ kDrawTextRSXform_OpType,
kDrawVertices_OpType,
kEndDrawPicture_OpType,
kRestore_OpType,
@@ -526,6 +528,26 @@ private:
typedef SkDrawCommand INHERITED;
};
+class SkDrawTextRSXformCommand : public SkDrawCommand {
+public:
+ SkDrawTextRSXformCommand(const void* text, size_t byteLength, const SkRSXform[],
+ const SkRect*, const SkPaint& paint);
+ ~SkDrawTextRSXformCommand() override { delete[] fText; delete[] fXform; }
+ void execute(SkCanvas* canvas) const override;
+ Json::Value toJSON(UrlDataManager& urlDataManager) const override;
+ static SkDrawTextRSXformCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
+
+private:
+ char* fText;
+ size_t fByteLength;
+ SkRSXform* fXform;
+ SkRect* fCull;
+ SkRect fCullStorage;
+ SkPaint fPaint;
+
+ typedef SkDrawCommand INHERITED;
+};
+
class SkDrawPosTextHCommand : public SkDrawCommand {
public:
SkDrawPosTextHCommand(const void* text, size_t byteLength, const SkScalar xpos[],