| Index: src/core/SkLiteDL.cpp
|
| diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
|
| index 283f4e686a81c15ad2ef19cc76eaac3d4d655da2..e3a4c0aa7598651967b764811234da777c6bb2e4 100644
|
| --- a/src/core/SkLiteDL.cpp
|
| +++ b/src/core/SkLiteDL.cpp
|
| @@ -10,11 +10,36 @@
|
| #include "SkLiteDL.h"
|
| #include "SkMutex.h"
|
| #include "SkSpinlock.h"
|
| +#include "SkTextBlob.h"
|
| +
|
| +// memcpy_v(dst, src0,bytes0, src1,bytes1, ...) copies an arbitrary number of srcs into dst.
|
| +static void memcpy_v(void* dst) {}
|
| +
|
| +template <typename... Rest>
|
| +static void memcpy_v(void* dst, const void* src, size_t bytes, Rest&&... rest) {
|
| + memcpy(dst, src, bytes);
|
| + memcpy_v(SkTAddOffset<void>(dst, bytes), std::forward<Rest>(rest)...);
|
| +}
|
| +
|
| +// Convert images and image-based shaders to textures.
|
| +static void optimize_for(GrContext* ctx, SkPaint* paint, sk_sp<const SkImage>* image = nullptr) {
|
| + SkMatrix matrix;
|
| + SkShader::TileMode xy[2];
|
| + if (auto shader = paint->getShader())
|
| + if (auto image = shader->isAImage(&matrix, xy)) { // TODO: compose shaders, etc.
|
| + paint->setShader(image->makeTextureImage(ctx)->makeShader(xy[0], xy[1], &matrix));
|
| + }
|
| +
|
| + if (image) {
|
| + *image = (*image)->makeTextureImage(ctx);
|
| + }
|
| +}
|
|
|
| namespace {
|
| struct Op {
|
| virtual ~Op() {}
|
| virtual void draw(SkCanvas*) = 0;
|
| + virtual void optimizeFor(GrContext*) {}
|
|
|
| size_t skip;
|
| };
|
| @@ -36,6 +61,7 @@ namespace {
|
| void draw(SkCanvas* c) override {
|
| c->saveLayer({ &bounds, &paint, backdrop.get(), flags });
|
| }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
|
|
| struct Concat final : Op {
|
| @@ -81,30 +107,35 @@ namespace {
|
| DrawPaint(const SkPaint& paint) : paint(paint) {}
|
| SkPaint paint;
|
| void draw(SkCanvas* c) override { c->drawPaint(paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
| struct DrawPath final : Op {
|
| DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
|
| SkPath path;
|
| SkPaint paint;
|
| void draw(SkCanvas* c) override { c->drawPath(path, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
| struct DrawRect final : Op {
|
| DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {}
|
| SkRect rect;
|
| SkPaint paint;
|
| void draw(SkCanvas* c) override { c->drawRect(rect, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
| struct DrawOval final : Op {
|
| DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {}
|
| SkRect oval;
|
| SkPaint paint;
|
| void draw(SkCanvas* c) override { c->drawOval(oval, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
| struct DrawRRect final : Op {
|
| DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {}
|
| SkRRect rrect;
|
| SkPaint paint;
|
| void draw(SkCanvas* c) override { c->drawRRect(rrect, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
| struct DrawDRRect final : Op {
|
| DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
|
| @@ -112,24 +143,108 @@ namespace {
|
| SkRRect outer, inner;
|
| SkPaint paint;
|
| void draw(SkCanvas* c) override { c->drawDRRect(outer, inner, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| };
|
|
|
| - template <typename T, typename... Args>
|
| - static void* push(SkTDArray<uint8_t>* bytes, size_t pod, Args&&... args) {
|
| - size_t skip = SkAlignPtr(sizeof(T) + pod);
|
| - auto op = (T*)bytes->append(skip);
|
| - new (op) T{ std::forward<Args>(args)... };
|
| - op->skip = skip;
|
| - return op+1;
|
| - }
|
| + struct DrawImage final : Op {
|
| + DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint)
|
| + : image(image), x(x), y(y) {
|
| + if (paint) { this->paint = *paint; }
|
| + }
|
| + sk_sp<const SkImage> image;
|
| + SkScalar x,y;
|
| + SkPaint paint;
|
| + void draw(SkCanvas* c) override { c->drawImage(image.get(), x,y, &paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
|
| + };
|
| + struct DrawImageNine final : Op {
|
| + DrawImageNine(sk_sp<const SkImage>&& image,
|
| + const SkIRect& center, const SkRect& dst, const SkPaint* paint)
|
| + : image(image), center(center), dst(dst) {
|
| + if (paint) { this->paint = *paint; }
|
| + }
|
| + sk_sp<const SkImage> image;
|
| + SkIRect center;
|
| + SkRect dst;
|
| + SkPaint paint;
|
| + void draw(SkCanvas* c) override { c->drawImageNine(image.get(), center, dst, &paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
|
| + };
|
| + struct DrawImageRect final : Op {
|
| + DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
|
| + const SkPaint* paint, SkCanvas::SrcRectConstraint constraint)
|
| + : image(image), dst(dst), constraint(constraint) {
|
| + this->src = src ? *src : SkRect::MakeIWH(image->width(), image->height());
|
| + if (paint) { this->paint = *paint; }
|
| + }
|
| + sk_sp<const SkImage> image;
|
| + SkRect src, dst;
|
| + SkPaint paint;
|
| + SkCanvas::SrcRectConstraint constraint;
|
| + void draw(SkCanvas* c) override {
|
| + c->drawImageRect(image.get(), src, dst, &paint, constraint);
|
| + }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); }
|
| + };
|
|
|
| - template <typename Fn>
|
| - static void map(SkTDArray<uint8_t>* bytes, Fn&& fn) {
|
| - for (uint8_t* ptr = bytes->begin(); ptr < bytes->end(); ) {
|
| - auto op = (Op*)ptr;
|
| - fn(op);
|
| - ptr += op->skip;
|
| + struct DrawText final : Op {
|
| + DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint)
|
| + : bytes(bytes), x(x), y(y), paint(paint) {}
|
| + size_t bytes;
|
| + SkScalar x,y;
|
| + SkPaint paint;
|
| + void draw(SkCanvas* c) override { c->drawText(this+1, bytes, x,y, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| + };
|
| + struct DrawPosText final : Op {
|
| + DrawPosText(size_t bytes, const SkPaint& paint)
|
| + : bytes(bytes), paint(paint) {}
|
| + size_t bytes;
|
| + SkPaint paint;
|
| + void draw(SkCanvas* c) override {
|
| + auto pos = SkTAddOffset<SkPoint>(this+1, bytes);
|
| + c->drawPosText(this+1, bytes, pos, paint);
|
| }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| + };
|
| + struct DrawPosTextH final : Op {
|
| + DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint)
|
| + : bytes(bytes), y(y), paint(paint) {}
|
| + size_t bytes;
|
| + SkScalar y;
|
| + SkPaint paint;
|
| + void draw(SkCanvas* c) override {
|
| + auto xs = SkTAddOffset<SkScalar>(this+1, bytes);
|
| + c->drawPosTextH(this+1, bytes, xs, y, paint);
|
| + }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| + };
|
| + struct DrawTextBlob final : Op {
|
| + DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
|
| + : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
|
| + sk_sp<const SkTextBlob> blob;
|
| + SkScalar x,y;
|
| + SkPaint paint;
|
| + void draw(SkCanvas* c) override { c->drawTextBlob(blob.get(), x,y, paint); }
|
| + void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); }
|
| + };
|
| +}
|
| +
|
| +template <typename T, typename... Args>
|
| +static void* push(SkTDArray<uint8_t>* bytes, size_t pod, Args&&... args) {
|
| + size_t skip = SkAlignPtr(sizeof(T) + pod);
|
| + auto op = (T*)bytes->append(skip);
|
| + new (op) T{ std::forward<Args>(args)... };
|
| + op->skip = skip;
|
| + return op+1;
|
| +}
|
| +
|
| +template <typename Fn>
|
| +static void map(SkTDArray<uint8_t>* bytes, Fn&& fn) {
|
| + for (uint8_t* ptr = bytes->begin(); ptr < bytes->end(); ) {
|
| + auto op = (Op*)ptr;
|
| + fn(op);
|
| + ptr += op->skip;
|
| }
|
| }
|
|
|
| @@ -175,10 +290,60 @@ void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPa
|
| push<DrawDRRect>(&fBytes, 0, outer, inner, paint);
|
| }
|
|
|
| +void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) {
|
| + push<DrawImage>(&fBytes, 0, SkImage::MakeFromBitmap(bm), x,y, paint);
|
| +}
|
| +void SkLiteDL::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
|
| + const SkRect& dst, const SkPaint* paint) {
|
| + push<DrawImageNine>(&fBytes, 0, SkImage::MakeFromBitmap(bm), center, dst, paint);
|
| +}
|
| +void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
|
| + const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
|
| + push<DrawImageRect>(&fBytes, 0, SkImage::MakeFromBitmap(bm), src, dst, paint, constraint);
|
| +}
|
| +
|
| +void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
|
| + push<DrawImage>(&fBytes, 0, sk_ref_sp(image), x,y, paint);
|
| +}
|
| +void SkLiteDL::drawImageNine(const SkImage* image, const SkIRect& center,
|
| + const SkRect& dst, const SkPaint* paint) {
|
| + push<DrawImageNine>(&fBytes, 0, sk_ref_sp(image), center, dst, paint);
|
| +}
|
| +void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
|
| + const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
|
| + push<DrawImageRect>(&fBytes, 0, sk_ref_sp(image), src, dst, paint, constraint);
|
| +}
|
| +
|
| +void SkLiteDL::drawText(const void* text, size_t bytes,
|
| + SkScalar x, SkScalar y, const SkPaint& paint) {
|
| + void* pod = push<DrawText>(&fBytes, bytes, bytes, x, y, paint);
|
| + memcpy_v(pod, text,bytes);
|
| +}
|
| +void SkLiteDL::drawPosText(const void* text, size_t bytes,
|
| + const SkPoint pos[], const SkPaint& paint) {
|
| + int n = paint.countText(text, bytes);
|
| + void* pod = push<DrawPosText>(&fBytes, bytes+n*sizeof(SkPoint), bytes, paint);
|
| + memcpy_v(pod, text,bytes, pos,n*sizeof(SkPoint));
|
| +}
|
| +void SkLiteDL::drawPosTextH(const void* text, size_t bytes,
|
| + const SkScalar xs[], SkScalar y, const SkPaint& paint) {
|
| + int n = paint.countText(text, bytes);
|
| + void* pod = push<DrawPosTextH>(&fBytes, bytes + n*sizeof(SkScalar), bytes, y, paint);
|
| + memcpy_v(pod, text,bytes, xs,n*sizeof(SkScalar));
|
| +}
|
| +void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
|
| + push<DrawTextBlob>(&fBytes, 0, blob, x,y, paint);
|
| +}
|
| +
|
| +
|
| void SkLiteDL::onDraw(SkCanvas* canvas) {
|
| map(&fBytes, [canvas](Op* op) { op->draw(canvas); });
|
| }
|
|
|
| +void SkLiteDL::optimizeFor(GrContext* ctx) {
|
| + map(&fBytes, [ctx](Op* op) { op->optimizeFor(ctx); });
|
| +}
|
| +
|
| SkRect SkLiteDL::onGetBounds() {
|
| return fBounds;
|
| }
|
|
|