aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2016-07-07 12:47:17 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-07 12:47:17 -0700
commit45561a0b15fe045ba272c328684c3f7ae290785a (patch)
tree185647ba5e92daf0899b1d8985dbf4a46a76f7b9 /src/core
parenta76a10b730ae3fb2abb7c06839ca9c5d14df5ca7 (diff)
drawTextRSXform
Diffstat (limited to 'src/core')
-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
9 files changed, 133 insertions, 0 deletions
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,