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; |
} |