#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;
};
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 {
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)
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;
}
}
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;
}
#include "SkRect.h"
#include "SkTDArray.h"
+class GrContext;
+
class SkLiteDL final : public SkDrawable {
public:
static sk_sp<SkLiteDL> New(SkRect);
+ void optimizeFor(GrContext*);
+
void save();
void saveLayer(const SkRect*, const SkPaint*, const SkImageFilter*, uint32_t);
void restore();
void drawPicture (const SkPicture*, const SkMatrix*, const SkPaint*) {/*TODO*/}
void drawShadowedPicture(const SkPicture*, const SkMatrix*, const SkPaint*) {/*TODO*/}
- void drawText (const void*, size_t, SkScalar, SkScalar, const SkPaint&) {/*TODO*/}
- void drawPosText (const void*, size_t, const SkPoint[], const SkPaint&) {/*TODO*/}
- void drawPosTextH (const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) {/*TODO*/}
+ void drawText (const void*, size_t, SkScalar, SkScalar, const SkPaint&);
+ void drawPosText (const void*, size_t, const SkPoint[], const SkPaint&);
+ void drawPosTextH (const void*, size_t, const SkScalar[], SkScalar, const SkPaint&);
void drawTextOnPath (const void*, size_t, const SkPath&, const SkMatrix*, const SkPaint&) {/*TODO*/}
void drawTextRSXForm(const void*, size_t, const SkRSXform[], const SkRect*, const SkPaint&) {/*TODO*/}
- void drawTextBlob (const SkTextBlob*, SkScalar,SkScalar, const SkPaint&) {/*TODO*/}
-
- void drawBitmap (const SkBitmap&, SkScalar,SkScalar, const SkPaint*) {/*TODO*/}
- void drawBitmapNine(const SkBitmap&, SkIRect, const SkRect&, const SkPaint*) {/*TODO*/}
- void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*, bool) {/*TODO*/}
-
- void drawImage (const SkImage*, SkScalar,SkScalar, const SkPaint*) {/*TODO*/}
- void drawImageNine (const SkImage*, SkIRect, const SkRect&, const SkPaint*) {/*TODO*/}
- void drawImageRect (const SkImage*, const SkRect*, const SkRect&, const SkPaint*, bool) {/*TODO*/}
- void drawImageLattice(const SkImage*, SkCanvas::Lattice, const SkRect&, const SkPaint*) {/*TODO*/}
+ void drawTextBlob (const SkTextBlob*, SkScalar,SkScalar, const SkPaint&);
+
+ void drawBitmap (const SkBitmap&, SkScalar, SkScalar, const SkPaint*);
+ void drawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, const SkPaint*);
+ void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
+ SkCanvas::SrcRectConstraint);
+
+ void drawImage (const SkImage*, SkScalar,SkScalar, const SkPaint*);
+ void drawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*);
+ void drawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
+ SkCanvas::SrcRectConstraint);
+ void drawImageLattice(const SkImage*, const SkCanvas::Lattice&, const SkRect&, const SkPaint*)
+ {/*TODO*/}
void drawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4],
SkXfermode*, const SkPaint&) {/*TODO*/}