diff options
author | 2016-07-07 12:47:17 -0700 | |
---|---|---|
committer | 2016-07-07 12:47:17 -0700 | |
commit | 45561a0b15fe045ba272c328684c3f7ae290785a (patch) | |
tree | 185647ba5e92daf0899b1d8985dbf4a46a76f7b9 /src/core | |
parent | a76a10b730ae3fb2abb7c06839ca9c5d14df5ca7 (diff) |
drawTextRSXform
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2130643004
Review-Url: https://codereview.chromium.org/2130643004
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkCanvas.cpp | 22 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 41 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 5 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 13 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 24 | ||||
-rw-r--r-- | src/core/SkPictureRecord.h | 2 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 11 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 10 | ||||
-rw-r--r-- | src/core/SkRecorder.h | 5 |
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, |