Index: src/core/SkLiteDL.cpp |
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp |
index e3a4c0aa7598651967b764811234da777c6bb2e4..77b1704d7052b6f5cdae4a314e48381dd2a9a1b4 100644 |
--- a/src/core/SkLiteDL.cpp |
+++ b/src/core/SkLiteDL.cpp |
@@ -6,21 +6,39 @@ |
*/ |
#include "SkCanvas.h" |
+#include "SkData.h" |
#include "SkImageFilter.h" |
#include "SkLiteDL.h" |
+#include "SkPicture.h" |
#include "SkMutex.h" |
+#include "SkRSXform.h" |
#include "SkSpinlock.h" |
#include "SkTextBlob.h" |
-// memcpy_v(dst, src0,bytes0, src1,bytes1, ...) copies an arbitrary number of srcs into dst. |
+// TODO: make sure DrawPosText and DrawPosTextH positions are aligned |
+// (move the text after the positions). |
+ |
+// A stand-in for an optional SkRect which was not set, e.g. bounds for a saveLayer(). |
+static const SkRect kUnset = {SK_ScalarInfinity, 0,0,0}; |
+static const SkRect* maybe_unset(const SkRect& r) { |
+ return r.left() == SK_ScalarInfinity ? nullptr : &r; |
+} |
+ |
+// memcpy_v(dst, src,bytes, src,bytes, ...) 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); |
+ sk_careful_memcpy(dst, src, bytes); |
memcpy_v(SkTAddOffset<void>(dst, bytes), std::forward<Rest>(rest)...); |
} |
+// Helper for getting back at arrays which have been memcpy_v'd together after an Op. |
+template <typename D, typename T> |
+static D* pod(T* op, size_t offset = 0) { |
+ return SkTAddOffset<D>(op+1, offset); |
+} |
+ |
// Convert images and image-based shaders to textures. |
static void optimize_for(GrContext* ctx, SkPaint* paint, sk_sp<const SkImage>* image = nullptr) { |
SkMatrix matrix; |
@@ -48,18 +66,18 @@ namespace { |
struct Restore final : Op { void draw(SkCanvas* c) override { c->restore(); } }; |
struct SaveLayer final : Op { |
SaveLayer(const SkRect* bounds, const SkPaint* paint, |
- const SkImageFilter* backdrop, uint32_t flags) { |
+ const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) { |
if (bounds) { this->bounds = *bounds; } |
if (paint) { this->paint = *paint; } |
this->backdrop = sk_ref_sp(backdrop); |
this->flags = flags; |
} |
- SkRect bounds = {SK_ScalarMin,SK_ScalarMin, SK_ScalarMax,SK_ScalarMax}; |
+ SkRect bounds = kUnset; |
SkPaint paint; |
sk_sp<const SkImageFilter> backdrop; |
- uint32_t flags; |
+ SkCanvas::SaveLayerFlags flags; |
void draw(SkCanvas* c) override { |
- c->saveLayer({ &bounds, &paint, backdrop.get(), flags }); |
+ c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags }); |
} |
void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
}; |
@@ -74,6 +92,15 @@ namespace { |
SkMatrix matrix; |
void draw(SkCanvas* c) override { c->setMatrix(matrix); } |
}; |
+ struct TranslateZ final : Op { |
+ TranslateZ(SkScalar dz) : dz(dz) {} |
+ SkScalar dz; |
+ void draw(SkCanvas* c) override { |
+ #ifdef SK_EXPERIMENTAL_SHADOWING |
+ c->translateZ(dz); |
+ #endif |
+ } |
+ }; |
struct ClipPath final : Op { |
ClipPath(const SkPath& path, SkRegion::Op op, bool aa) : path(path), op(op), aa(aa) {} |
@@ -146,6 +173,49 @@ namespace { |
void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
}; |
+ struct DrawAnnotation final : Op { |
+ DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {} |
+ SkRect rect; |
+ sk_sp<SkData> value; |
+ void draw(SkCanvas* c) override { c->drawAnnotation(rect, pod<char>(this), value.get()); } |
+ }; |
+ struct DrawDrawable final : Op { |
+ DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) { |
+ if (matrix) { this->matrix = *matrix; } |
+ } |
+ sk_sp<SkDrawable> drawable; |
+ SkMatrix matrix = SkMatrix::I(); |
+ void draw(SkCanvas* c) override { c->drawDrawable(drawable.get(), &matrix); } |
+ }; |
+ struct DrawPicture final : Op { |
+ DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) |
+ : picture(sk_ref_sp(picture)) { |
+ if (matrix) { this->matrix = *matrix; } |
+ if (paint) { this->paint = *paint; } |
+ } |
+ sk_sp<const SkPicture> picture; |
+ SkMatrix matrix = SkMatrix::I(); |
+ SkPaint paint; |
+ void draw(SkCanvas* c) override { c->drawPicture(picture.get(), &matrix, &paint); } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
+ }; |
+ struct DrawShadowedPicture final : Op { |
+ DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) |
+ : picture(sk_ref_sp(picture)) { |
+ if (matrix) { this->matrix = *matrix; } |
+ if (paint) { this->paint = *paint; } |
+ } |
+ sk_sp<const SkPicture> picture; |
+ SkMatrix matrix = SkMatrix::I(); |
+ SkPaint paint; |
+ void draw(SkCanvas* c) override { |
+ #ifdef SK_EXPERIMENTAL_SHADOWING |
+ c->drawShadowedPicture(picture.get(), &matrix, &paint); |
+ #endif |
+ } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
+ }; |
+ |
struct DrawImage final : Op { |
DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint) |
: image(image), x(x), y(y) { |
@@ -186,6 +256,23 @@ namespace { |
} |
void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); } |
}; |
+ struct DrawImageLattice final : Op { |
+ DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, |
+ const SkRect& dst, const SkPaint* paint) |
+ : image(image), xs(xs), ys(ys), dst(dst) { |
+ if (paint) { this->paint = *paint; } |
+ } |
+ sk_sp<const SkImage> image; |
+ int xs, ys; |
+ SkRect dst; |
+ SkPaint paint; |
+ void draw(SkCanvas* c) override { |
+ auto xdivs = pod<int>(this, 0), |
+ ydivs = pod<int>(this, xs*sizeof(int)); |
+ c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint); |
+ } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &image); } |
+ }; |
struct DrawText final : Op { |
DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint) |
@@ -193,7 +280,7 @@ namespace { |
size_t bytes; |
SkScalar x,y; |
SkPaint paint; |
- void draw(SkCanvas* c) override { c->drawText(this+1, bytes, x,y, paint); } |
+ void draw(SkCanvas* c) override { c->drawText(pod<void>(this), bytes, x,y, paint); } |
void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
}; |
struct DrawPosText final : Op { |
@@ -202,20 +289,47 @@ namespace { |
size_t bytes; |
SkPaint paint; |
void draw(SkCanvas* c) override { |
- auto pos = SkTAddOffset<SkPoint>(this+1, bytes); |
- c->drawPosText(this+1, bytes, pos, paint); |
+ c->drawPosText(pod<void>(this), bytes, pod<SkPoint>(this, bytes), 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; |
+ size_t bytes; |
SkScalar y; |
+ SkPaint paint; |
+ void draw(SkCanvas* c) override { |
+ c->drawPosTextH(pod<void>(this), bytes, pod<SkScalar>(this, bytes), y, paint); |
+ } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
+ }; |
+ struct DrawTextOnPath final : Op { |
+ DrawTextOnPath(size_t bytes, const SkPath& path, |
+ const SkMatrix* matrix, const SkPaint& paint) |
+ : bytes(bytes), path(path), paint(paint) { |
+ if (matrix) { this->matrix = *matrix; } |
+ } |
+ size_t bytes; |
+ SkPath path; |
+ SkMatrix matrix = SkMatrix::I(); |
+ SkPaint paint; |
+ void draw(SkCanvas* c) override { |
+ c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint); |
+ } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
+ }; |
+ struct DrawTextRSXform final : Op { |
+ DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint) |
+ : bytes(bytes), paint(paint) { |
+ if (cull) { this->cull = *cull; } |
+ } |
+ size_t bytes; |
+ SkRect cull = kUnset; |
SkPaint paint; |
void draw(SkCanvas* c) override { |
- auto xs = SkTAddOffset<SkScalar>(this+1, bytes); |
- c->drawPosTextH(this+1, bytes, xs, y, paint); |
+ c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes), |
+ maybe_unset(cull), paint); |
} |
void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
}; |
@@ -228,6 +342,40 @@ namespace { |
void draw(SkCanvas* c) override { c->drawTextBlob(blob.get(), x,y, paint); } |
void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
}; |
+ |
+ struct DrawPoints final : Op { |
+ DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint) |
+ : mode(mode), count(count), paint(paint) {} |
+ SkCanvas::PointMode mode; |
+ size_t count; |
+ SkPaint paint; |
+ void draw(SkCanvas* c) override { c->drawPoints(mode, count, pod<SkPoint>(this), paint); } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint); } |
+ }; |
+ struct DrawAtlas final : Op { |
+ DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode, |
+ const SkRect* cull, const SkPaint* paint, bool has_colors) |
+ : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) { |
+ if (cull) { this->cull = *cull; } |
+ if (paint) { this->paint = *paint; } |
+ } |
+ sk_sp<const SkImage> atlas; |
+ int count; |
+ SkXfermode::Mode xfermode; |
+ SkRect cull = kUnset; |
+ SkPaint paint; |
+ bool has_colors; |
+ void draw(SkCanvas* c) override { |
+ auto xforms = pod<SkRSXform>(this, 0); |
+ auto texs = pod<SkRect>(this, count*sizeof(SkRSXform)); |
+ auto colors = has_colors |
+ ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect))) |
+ : nullptr; |
+ c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode, |
+ maybe_unset(cull), &paint); |
+ } |
+ void optimizeFor(GrContext* ctx) override { optimize_for(ctx, &paint, &atlas); } |
+ }; |
} |
template <typename T, typename... Args> |
@@ -251,12 +399,13 @@ static void map(SkTDArray<uint8_t>* bytes, Fn&& fn) { |
void SkLiteDL:: save() { push <Save>(&fBytes, 0); } |
void SkLiteDL::restore() { push<Restore>(&fBytes, 0); } |
void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint, |
- const SkImageFilter* backdrop, uint32_t flags) { |
+ const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) { |
push<SaveLayer>(&fBytes, 0, bounds, paint, backdrop, flags); |
} |
void SkLiteDL:: concat(const SkMatrix& matrix) { push <Concat>(&fBytes, 0, matrix); } |
void SkLiteDL::setMatrix(const SkMatrix& matrix) { push<SetMatrix>(&fBytes, 0, matrix); } |
+void SkLiteDL::translateZ(SkScalar dz) { push<TranslateZ>(&fBytes, 0, dz); } |
void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) { |
push<ClipPath>(&fBytes, 0, path, op, aa); |
@@ -290,6 +439,23 @@ void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPa |
push<DrawDRRect>(&fBytes, 0, outer, inner, paint); |
} |
+void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) { |
+ size_t bytes = strlen(key)+1; |
+ void* pod = push<DrawAnnotation>(&fBytes, bytes, rect, value); |
+ memcpy_v(pod, key,bytes); |
+} |
+void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { |
+ push<DrawDrawable>(&fBytes, 0, drawable, matrix); |
+} |
+void SkLiteDL::drawPicture(const SkPicture* picture, |
+ const SkMatrix* matrix, const SkPaint* paint) { |
+ push<DrawPicture>(&fBytes, 0, picture, matrix, paint); |
+} |
+void SkLiteDL::drawShadowedPicture(const SkPicture* picture, |
+ const SkMatrix* matrix, const SkPaint* paint) { |
+ push<DrawShadowedPicture>(&fBytes, 0, picture, matrix, paint); |
+} |
+ |
void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) { |
push<DrawImage>(&fBytes, 0, SkImage::MakeFromBitmap(bm), x,y, paint); |
} |
@@ -313,6 +479,14 @@ void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRe |
const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { |
push<DrawImageRect>(&fBytes, 0, sk_ref_sp(image), src, dst, paint, constraint); |
} |
+void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice, |
+ const SkRect& dst, const SkPaint* paint) { |
+ int xs = lattice.fXCount, ys = lattice.fYCount; |
+ size_t bytes = (xs + ys) * sizeof(int); |
+ void* pod = push<DrawImageLattice>(&fBytes, bytes, sk_ref_sp(image), xs, ys, dst, paint); |
+ memcpy_v(pod, lattice.fXDivs,xs*sizeof(int), |
+ lattice.fYDivs,ys*sizeof(int)); |
+} |
void SkLiteDL::drawText(const void* text, size_t bytes, |
SkScalar x, SkScalar y, const SkPaint& paint) { |
@@ -328,13 +502,43 @@ void SkLiteDL::drawPosText(const void* text, size_t bytes, |
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); |
+ void* pod = push<DrawPosTextH>(&fBytes, bytes+n*sizeof(SkScalar), bytes, y, paint); |
memcpy_v(pod, text,bytes, xs,n*sizeof(SkScalar)); |
} |
+void SkLiteDL::drawTextOnPath(const void* text, size_t bytes, |
+ const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { |
+ void* pod = push<DrawTextOnPath>(&fBytes, bytes, bytes, path, matrix, paint); |
+ memcpy_v(pod, text,bytes); |
+} |
+void SkLiteDL::drawTextRSXform(const void* text, size_t bytes, |
+ const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) { |
+ int n = paint.countText(text, bytes); |
+ void* pod = push<DrawTextRSXform>(&fBytes, bytes+n*sizeof(SkRSXform), bytes, cull, paint); |
+ memcpy_v(pod, text,bytes, xforms,n*sizeof(SkRSXform)); |
+} |
void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { |
push<DrawTextBlob>(&fBytes, 0, blob, x,y, paint); |
} |
+void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[], |
+ const SkPaint& paint) { |
+ void* pod = push<DrawPoints>(&fBytes, count*sizeof(SkPoint), mode, count, paint); |
+ memcpy_v(pod, points,count*sizeof(SkPoint)); |
+} |
+void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[], |
+ const SkColor colors[], int count, SkXfermode::Mode xfermode, |
+ const SkRect* cull, const SkPaint* paint) { |
+ size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect)); |
+ if (colors) { |
+ bytes += count*sizeof(SkColor); |
+ } |
+ void* pod = push<DrawAtlas>(&fBytes, bytes, |
+ atlas, count, xfermode, cull, paint, colors != nullptr); |
+ memcpy_v(pod, xforms, count*sizeof(SkRSXform), |
+ texs, count*sizeof(SkRect), |
+ colors, colors ? count*sizeof(SkColor) : 0); |
+} |
+ |
void SkLiteDL::onDraw(SkCanvas* canvas) { |
map(&fBytes, [canvas](Op* op) { op->draw(canvas); }); |