diff options
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[], |