| /* | |
| * Copyright 2016 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkCanvas.h" | |
| #include "SkData.h" | |
| #include "SkDrawShadowInfo.h" | |
| #include "SkImage.h" | |
| #include "SkImageFilter.h" | |
| #include "SkLiteDL.h" | |
| #include "SkMath.h" | |
| #include "SkPicture.h" | |
| #include "SkRegion.h" | |
| #include "SkRSXform.h" | |
| #include "SkTextBlob.h" | |
| #include "SkVertices.h" | |
| #ifndef SKLITEDL_PAGE | |
| #define SKLITEDL_PAGE 4096 | |
| #endif | |
| // 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; | |
| } | |
| // copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into dst. | |
| static void copy_v(void* dst) {} | |
| template <typename S, typename... Rest> | |
| static void copy_v(void* dst, const S* src, int n, Rest&&... rest) { | |
| SkASSERTF(((uintptr_t)dst & (alignof(S)-1)) == 0, | |
| "Expected %p to be aligned for at least %zu bytes.", dst, alignof(S)); | |
| sk_careful_memcpy(dst, src, n*sizeof(S)); | |
| copy_v(SkTAddOffset<void>(dst, n*sizeof(S)), std::forward<Rest>(rest)...); | |
| } | |
| // Helper for getting back at arrays which have been copy_v'd together after an Op. | |
| template <typename D, typename T> | |
| static const D* pod(const T* op, size_t offset = 0) { | |
| return SkTAddOffset<const D>(op+1, offset); | |
| } | |
| namespace { | |
| #define TYPES(M) \ | |
| M(Flush) M(Save) M(Restore) M(SaveLayer) \ | |
| M(Concat) M(SetMatrix) M(Translate) \ | |
| M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \ | |
| M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawRegion) M(DrawOval) M(DrawArc) \ | |
| M(DrawRRect) M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \ | |
| M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) \ | |
| M(DrawText) M(DrawPosText) M(DrawPosTextH) \ | |
| M(DrawTextRSXform) M(DrawTextBlob) \ | |
| M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas) M(DrawShadowRec) | |
| #define M(T) T, | |
| enum class Type : uint8_t { TYPES(M) }; | |
| #undef M | |
| struct Op { | |
| uint32_t type : 8; | |
| uint32_t skip : 24; | |
| }; | |
| static_assert(sizeof(Op) == 4, ""); | |
| struct Flush final : Op { | |
| static const auto kType = Type::Flush; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->flush(); } | |
| }; | |
| struct Save final : Op { | |
| static const auto kType = Type::Save; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->save(); } | |
| }; | |
| struct Restore final : Op { | |
| static const auto kType = Type::Restore; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->restore(); } | |
| }; | |
| struct SaveLayer final : Op { | |
| static const auto kType = Type::SaveLayer; | |
| SaveLayer(const SkRect* bounds, const SkPaint* paint, | |
| const SkImageFilter* backdrop, const SkImage* clipMask, | |
| const SkMatrix* clipMatrix, SkCanvas::SaveLayerFlags flags) { | |
| if (bounds) { this->bounds = *bounds; } | |
| if (paint) { this->paint = *paint; } | |
| this->backdrop = sk_ref_sp(backdrop); | |
| this->clipMask = sk_ref_sp(clipMask); | |
| this->clipMatrix = clipMatrix ? *clipMatrix : SkMatrix::I(); | |
| this->flags = flags; | |
| } | |
| SkRect bounds = kUnset; | |
| SkPaint paint; | |
| sk_sp<const SkImageFilter> backdrop; | |
| sk_sp<const SkImage> clipMask; | |
| SkMatrix clipMatrix; | |
| SkCanvas::SaveLayerFlags flags; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), clipMask.get(), | |
| clipMatrix.isIdentity() ? nullptr : &clipMatrix, flags }); | |
| } | |
| }; | |
| struct Concat final : Op { | |
| static const auto kType = Type::Concat; | |
| Concat(const SkMatrix& matrix) : matrix(matrix) {} | |
| SkMatrix matrix; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->concat(matrix); } | |
| }; | |
| struct SetMatrix final : Op { | |
| static const auto kType = Type::SetMatrix; | |
| SetMatrix(const SkMatrix& matrix) : matrix(matrix) {} | |
| SkMatrix matrix; | |
| void draw(SkCanvas* c, const SkMatrix& original) const { | |
| c->setMatrix(SkMatrix::Concat(original, matrix)); | |
| } | |
| }; | |
| struct Translate final : Op { | |
| static const auto kType = Type::Translate; | |
| Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {} | |
| SkScalar dx,dy; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->translate(dx, dy); | |
| } | |
| }; | |
| struct ClipPath final : Op { | |
| static const auto kType = Type::ClipPath; | |
| ClipPath(const SkPath& path, SkClipOp op, bool aa) : path(path), op(op), aa(aa) {} | |
| SkPath path; | |
| SkClipOp op; | |
| bool aa; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->clipPath(path, op, aa); } | |
| }; | |
| struct ClipRect final : Op { | |
| static const auto kType = Type::ClipRect; | |
| ClipRect(const SkRect& rect, SkClipOp op, bool aa) : rect(rect), op(op), aa(aa) {} | |
| SkRect rect; | |
| SkClipOp op; | |
| bool aa; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->clipRect(rect, op, aa); } | |
| }; | |
| struct ClipRRect final : Op { | |
| static const auto kType = Type::ClipRRect; | |
| ClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) : rrect(rrect), op(op), aa(aa) {} | |
| SkRRect rrect; | |
| SkClipOp op; | |
| bool aa; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->clipRRect(rrect, op, aa); } | |
| }; | |
| struct ClipRegion final : Op { | |
| static const auto kType = Type::ClipRegion; | |
| ClipRegion(const SkRegion& region, SkClipOp op) : region(region), op(op) {} | |
| SkRegion region; | |
| SkClipOp op; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->clipRegion(region, op); } | |
| }; | |
| struct DrawPaint final : Op { | |
| static const auto kType = Type::DrawPaint; | |
| DrawPaint(const SkPaint& paint) : paint(paint) {} | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawPaint(paint); } | |
| }; | |
| struct DrawPath final : Op { | |
| static const auto kType = Type::DrawPath; | |
| DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {} | |
| SkPath path; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawPath(path, paint); } | |
| }; | |
| struct DrawRect final : Op { | |
| static const auto kType = Type::DrawRect; | |
| DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {} | |
| SkRect rect; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawRect(rect, paint); } | |
| }; | |
| struct DrawRegion final : Op { | |
| static const auto kType = Type::DrawRegion; | |
| DrawRegion(const SkRegion& region, const SkPaint& paint) : region(region), paint(paint) {} | |
| SkRegion region; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawRegion(region, paint); } | |
| }; | |
| struct DrawOval final : Op { | |
| static const auto kType = Type::DrawOval; | |
| DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {} | |
| SkRect oval; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawOval(oval, paint); } | |
| }; | |
| struct DrawArc final : Op { | |
| static const auto kType = Type::DrawArc; | |
| DrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, | |
| const SkPaint& paint) | |
| : oval(oval), startAngle(startAngle), sweepAngle(sweepAngle), useCenter(useCenter) | |
| , paint(paint) {} | |
| SkRect oval; | |
| SkScalar startAngle; | |
| SkScalar sweepAngle; | |
| bool useCenter; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawArc(oval, startAngle, sweepAngle, | |
| useCenter, paint); } | |
| }; | |
| struct DrawRRect final : Op { | |
| static const auto kType = Type::DrawRRect; | |
| DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {} | |
| SkRRect rrect; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawRRect(rrect, paint); } | |
| }; | |
| struct DrawDRRect final : Op { | |
| static const auto kType = Type::DrawDRRect; | |
| DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) | |
| : outer(outer), inner(inner), paint(paint) {} | |
| SkRRect outer, inner; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawDRRect(outer, inner, paint); } | |
| }; | |
| struct DrawAnnotation final : Op { | |
| static const auto kType = Type::DrawAnnotation; | |
| DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {} | |
| SkRect rect; | |
| sk_sp<SkData> value; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->drawAnnotation(rect, pod<char>(this), value.get()); | |
| } | |
| }; | |
| struct DrawDrawable final : Op { | |
| static const auto kType = Type::DrawDrawable; | |
| 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, const SkMatrix&) const { | |
| c->drawDrawable(drawable.get(), &matrix); | |
| } | |
| }; | |
| struct DrawPicture final : Op { | |
| static const auto kType = Type::DrawPicture; | |
| 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; has_paint = true; } | |
| } | |
| sk_sp<const SkPicture> picture; | |
| SkMatrix matrix = SkMatrix::I(); | |
| SkPaint paint; | |
| bool has_paint = false; // TODO: why is a default paint not the same? | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr); | |
| } | |
| }; | |
| struct DrawImage final : Op { | |
| static const auto kType = Type::DrawImage; | |
| DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint) | |
| : image(std::move(image)), x(x), y(y) { | |
| if (paint) { this->paint = *paint; } | |
| } | |
| sk_sp<const SkImage> image; | |
| SkScalar x,y; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { c->drawImage(image.get(), x,y, &paint); } | |
| }; | |
| struct DrawImageNine final : Op { | |
| static const auto kType = Type::DrawImageNine; | |
| DrawImageNine(sk_sp<const SkImage>&& image, | |
| const SkIRect& center, const SkRect& dst, const SkPaint* paint) | |
| : image(std::move(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, const SkMatrix&) const { | |
| c->drawImageNine(image.get(), center, dst, &paint); | |
| } | |
| }; | |
| struct DrawImageRect final : Op { | |
| static const auto kType = Type::DrawImageRect; | |
| DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst, | |
| const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) | |
| : image(std::move(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, const SkMatrix&) const { | |
| c->drawImageRect(image.get(), src, dst, &paint, constraint); | |
| } | |
| }; | |
| struct DrawImageLattice final : Op { | |
| static const auto kType = Type::DrawImageLattice; | |
| DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs, | |
| const SkIRect& src, const SkRect& dst, const SkPaint* paint) | |
| : image(std::move(image)), xs(xs), ys(ys), fs(fs), src(src), dst(dst) { | |
| if (paint) { this->paint = *paint; } | |
| } | |
| sk_sp<const SkImage> image; | |
| int xs, ys, fs; | |
| SkIRect src; | |
| SkRect dst; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| auto xdivs = pod<int>(this, 0), | |
| ydivs = pod<int>(this, xs*sizeof(int)); | |
| auto colors = (0 == fs) ? nullptr : | |
| pod<SkColor>(this, (xs+ys)*sizeof(int)); | |
| auto flags = (0 == fs) ? nullptr : | |
| pod<SkCanvas::Lattice::RectType>(this, (xs+ys)*sizeof(int)+ | |
| fs*sizeof(SkColor)); | |
| c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src, colors}, dst, | |
| &paint); | |
| } | |
| }; | |
| struct DrawText final : Op { | |
| static const auto kType = Type::DrawText; | |
| 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, const SkMatrix&) const { | |
| c->drawText(pod<void>(this), bytes, x,y, paint); | |
| } | |
| }; | |
| struct DrawPosText final : Op { | |
| static const auto kType = Type::DrawPosText; | |
| DrawPosText(size_t bytes, const SkPaint& paint, int n) | |
| : bytes(bytes), paint(paint), n(n) {} | |
| size_t bytes; | |
| SkPaint paint; | |
| int n; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| auto points = pod<SkPoint>(this); | |
| auto text = pod<void>(this, n*sizeof(SkPoint)); | |
| c->drawPosText(text, bytes, points, paint); | |
| } | |
| }; | |
| struct DrawPosTextH final : Op { | |
| static const auto kType = Type::DrawPosTextH; | |
| DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n) | |
| : bytes(bytes), y(y), paint(paint), n(n) {} | |
| size_t bytes; | |
| SkScalar y; | |
| SkPaint paint; | |
| int n; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| auto xs = pod<SkScalar>(this); | |
| auto text = pod<void>(this, n*sizeof(SkScalar)); | |
| c->drawPosTextH(text, bytes, xs, y, paint); | |
| } | |
| }; | |
| struct DrawTextRSXform final : Op { | |
| static const auto kType = Type::DrawTextRSXform; | |
| DrawTextRSXform(size_t bytes, int xforms, const SkRect* cull, const SkPaint& paint) | |
| : bytes(bytes), xforms(xforms), paint(paint) { | |
| if (cull) { this->cull = *cull; } | |
| } | |
| size_t bytes; | |
| int xforms; | |
| SkRect cull = kUnset; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| // For alignment, the SkRSXforms are first in the pod section, followed by the text. | |
| c->drawTextRSXform(pod<void>(this,xforms*sizeof(SkRSXform)), | |
| bytes, | |
| pod<SkRSXform>(this), | |
| maybe_unset(cull), | |
| paint); | |
| } | |
| }; | |
| struct DrawTextBlob final : Op { | |
| static const auto kType = Type::DrawTextBlob; | |
| 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, const SkMatrix&) const { | |
| c->drawTextBlob(blob.get(), x,y, paint); | |
| } | |
| }; | |
| struct DrawPatch final : Op { | |
| static const auto kType = Type::DrawPatch; | |
| DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4], | |
| SkBlendMode bmode, const SkPaint& paint) | |
| : xfermode(bmode), paint(paint) | |
| { | |
| copy_v(this->cubics, cubics, 12); | |
| if (colors) { copy_v(this->colors, colors, 4); has_colors = true; } | |
| if (texs ) { copy_v(this->texs , texs , 4); has_texs = true; } | |
| } | |
| SkPoint cubics[12]; | |
| SkColor colors[4]; | |
| SkPoint texs[4]; | |
| SkBlendMode xfermode; | |
| SkPaint paint; | |
| bool has_colors = false; | |
| bool has_texs = false; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr, | |
| xfermode, paint); | |
| } | |
| }; | |
| struct DrawPoints final : Op { | |
| static const auto kType = Type::DrawPoints; | |
| 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, const SkMatrix&) const { | |
| c->drawPoints(mode, count, pod<SkPoint>(this), paint); | |
| } | |
| }; | |
| struct DrawVertices final : Op { | |
| static const auto kType = Type::DrawVertices; | |
| DrawVertices(const SkVertices* v, int bc, SkBlendMode m, const SkPaint& p) | |
| : vertices(sk_ref_sp(const_cast<SkVertices*>(v))) | |
| , boneCount(bc) | |
| , mode(m) | |
| , paint(p) {} | |
| sk_sp<SkVertices> vertices; | |
| int boneCount; | |
| SkBlendMode mode; | |
| SkPaint paint; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->drawVertices(vertices, pod<SkVertices::Bone>(this), boneCount, mode, paint); | |
| } | |
| }; | |
| struct DrawAtlas final : Op { | |
| static const auto kType = Type::DrawAtlas; | |
| DrawAtlas(const SkImage* atlas, int count, SkBlendMode 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; | |
| SkBlendMode xfermode; | |
| SkRect cull = kUnset; | |
| SkPaint paint; | |
| bool has_colors; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| 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); | |
| } | |
| }; | |
| struct DrawShadowRec final : Op { | |
| static const auto kType = Type::DrawShadowRec; | |
| DrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) | |
| : fPath(path), fRec(rec) | |
| {} | |
| SkPath fPath; | |
| SkDrawShadowRec fRec; | |
| void draw(SkCanvas* c, const SkMatrix&) const { | |
| c->private_draw_shadow_rec(fPath, fRec); | |
| } | |
| }; | |
| } | |
| template <typename T, typename... Args> | |
| void* SkLiteDL::push(size_t pod, Args&&... args) { | |
| size_t skip = SkAlignPtr(sizeof(T) + pod); | |
| SkASSERT(skip < (1<<24)); | |
| if (fUsed + skip > fReserved) { | |
| static_assert(SkIsPow2(SKLITEDL_PAGE), "This math needs updating for non-pow2."); | |
| // Next greater multiple of SKLITEDL_PAGE. | |
| fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE-1); | |
| fBytes.realloc(fReserved); | |
| } | |
| SkASSERT(fUsed + skip <= fReserved); | |
| auto op = (T*)(fBytes.get() + fUsed); | |
| fUsed += skip; | |
| new (op) T{ std::forward<Args>(args)... }; | |
| op->type = (uint32_t)T::kType; | |
| op->skip = skip; | |
| return op+1; | |
| } | |
| template <typename Fn, typename... Args> | |
| inline void SkLiteDL::map(const Fn fns[], Args... args) const { | |
| auto end = fBytes.get() + fUsed; | |
| for (const uint8_t* ptr = fBytes.get(); ptr < end; ) { | |
| auto op = (const Op*)ptr; | |
| auto type = op->type; | |
| auto skip = op->skip; | |
| if (auto fn = fns[type]) { // We replace no-op functions with nullptrs | |
| fn(op, args...); // to avoid the overhead of a pointless call. | |
| } | |
| ptr += skip; | |
| } | |
| } | |
| void SkLiteDL::flush() { this->push<Flush>(0); } | |
| void SkLiteDL:: save() { this->push <Save>(0); } | |
| void SkLiteDL::restore() { this->push<Restore>(0); } | |
| void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint, | |
| const SkImageFilter* backdrop, const SkImage* clipMask, | |
| const SkMatrix* clipMatrix, SkCanvas::SaveLayerFlags flags) { | |
| this->push<SaveLayer>(0, bounds, paint, backdrop, clipMask, clipMatrix, flags); | |
| } | |
| void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); } | |
| void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); } | |
| void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); } | |
| void SkLiteDL::clipPath(const SkPath& path, SkClipOp op, bool aa) { | |
| this->push<ClipPath>(0, path, op, aa); | |
| } | |
| void SkLiteDL::clipRect(const SkRect& rect, SkClipOp op, bool aa) { | |
| this->push<ClipRect>(0, rect, op, aa); | |
| } | |
| void SkLiteDL::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { | |
| this->push<ClipRRect>(0, rrect, op, aa); | |
| } | |
| void SkLiteDL::clipRegion(const SkRegion& region, SkClipOp op) { | |
| this->push<ClipRegion>(0, region, op); | |
| } | |
| void SkLiteDL::drawPaint(const SkPaint& paint) { | |
| this->push<DrawPaint>(0, paint); | |
| } | |
| void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) { | |
| this->push<DrawPath>(0, path, paint); | |
| } | |
| void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) { | |
| this->push<DrawRect>(0, rect, paint); | |
| } | |
| void SkLiteDL::drawRegion(const SkRegion& region, const SkPaint& paint) { | |
| this->push<DrawRegion>(0, region, paint); | |
| } | |
| void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) { | |
| this->push<DrawOval>(0, oval, paint); | |
| } | |
| void SkLiteDL::drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, | |
| const SkPaint& paint) { | |
| this->push<DrawArc>(0, oval, startAngle, sweepAngle, useCenter, paint); | |
| } | |
| void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) { | |
| this->push<DrawRRect>(0, rrect, paint); | |
| } | |
| void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { | |
| this->push<DrawDRRect>(0, outer, inner, paint); | |
| } | |
| void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) { | |
| size_t bytes = strlen(key)+1; | |
| void* pod = this->push<DrawAnnotation>(bytes, rect, value); | |
| copy_v(pod, key,bytes); | |
| } | |
| void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { | |
| this->push<DrawDrawable>(0, drawable, matrix); | |
| } | |
| void SkLiteDL::drawPicture(const SkPicture* picture, | |
| const SkMatrix* matrix, const SkPaint* paint) { | |
| this->push<DrawPicture>(0, picture, matrix, paint); | |
| } | |
| void SkLiteDL::drawImage(sk_sp<const SkImage> image, SkScalar x, SkScalar y, const SkPaint* paint) { | |
| this->push<DrawImage>(0, std::move(image), x,y, paint); | |
| } | |
| void SkLiteDL::drawImageNine(sk_sp<const SkImage> image, const SkIRect& center, | |
| const SkRect& dst, const SkPaint* paint) { | |
| this->push<DrawImageNine>(0, std::move(image), center, dst, paint); | |
| } | |
| void SkLiteDL::drawImageRect(sk_sp<const SkImage> image, const SkRect* src, const SkRect& dst, | |
| const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { | |
| this->push<DrawImageRect>(0, std::move(image), src, dst, paint, constraint); | |
| } | |
| void SkLiteDL::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice, | |
| const SkRect& dst, const SkPaint* paint) { | |
| int xs = lattice.fXCount, ys = lattice.fYCount; | |
| int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0; | |
| size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType) | |
| + fs * sizeof(SkColor); | |
| SkASSERT(lattice.fBounds); | |
| void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds, | |
| dst, paint); | |
| copy_v(pod, lattice.fXDivs, xs, | |
| lattice.fYDivs, ys, | |
| lattice.fColors, fs, | |
| lattice.fRectTypes, fs); | |
| } | |
| void SkLiteDL::drawText(const void* text, size_t bytes, | |
| SkScalar x, SkScalar y, const SkPaint& paint) { | |
| void* pod = this->push<DrawText>(bytes, bytes, x, y, paint); | |
| copy_v(pod, (const char*)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 = this->push<DrawPosText>(n*sizeof(SkPoint)+bytes, bytes, paint, n); | |
| copy_v(pod, pos,n, (const char*)text,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 = this->push<DrawPosTextH>(n*sizeof(SkScalar)+bytes, bytes, y, paint, n); | |
| copy_v(pod, xs,n, (const char*)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 = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, n, cull, paint); | |
| copy_v(pod, xforms,n, (const char*)text,bytes); | |
| } | |
| void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { | |
| this->push<DrawTextBlob>(0, blob, x,y, paint); | |
| } | |
| void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4], | |
| SkBlendMode bmode, const SkPaint& paint) { | |
| this->push<DrawPatch>(0, points, colors, texs, bmode, paint); | |
| } | |
| void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[], | |
| const SkPaint& paint) { | |
| void* pod = this->push<DrawPoints>(count*sizeof(SkPoint), mode, count, paint); | |
| copy_v(pod, points,count); | |
| } | |
| void SkLiteDL::drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[], | |
| int boneCount, SkBlendMode mode, const SkPaint& paint) { | |
| void* pod = this->push<DrawVertices>(boneCount * sizeof(SkVertices::Bone), | |
| vertices, | |
| boneCount, | |
| mode, | |
| paint); | |
| copy_v(pod, bones, boneCount); | |
| } | |
| void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[], | |
| const SkColor colors[], int count, SkBlendMode xfermode, | |
| const SkRect* cull, const SkPaint* paint) { | |
| size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect)); | |
| if (colors) { | |
| bytes += count*sizeof(SkColor); | |
| } | |
| void* pod = this->push<DrawAtlas>(bytes, | |
| atlas, count, xfermode, cull, paint, colors != nullptr); | |
| copy_v(pod, xforms, count, | |
| texs, count, | |
| colors, colors ? count : 0); | |
| } | |
| void SkLiteDL::drawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { | |
| this->push<DrawShadowRec>(0, path, rec); | |
| } | |
| typedef void(*draw_fn)(const void*, SkCanvas*, const SkMatrix&); | |
| typedef void(*void_fn)(const void*); | |
| // All ops implement draw(). | |
| #define M(T) [](const void* op, SkCanvas* c, const SkMatrix& original) { \ | |
| ((const T*)op)->draw(c, original); \ | |
| }, | |
| static const draw_fn draw_fns[] = { TYPES(M) }; | |
| #undef M | |
| // Most state ops (matrix, clip, save, restore) have a trivial destructor. | |
| #define M(T) !std::is_trivially_destructible<T>::value \ | |
| ? [](const void* op) { ((const T*)op)->~T(); } \ | |
| : (void_fn)nullptr, | |
| static const void_fn dtor_fns[] = { TYPES(M) }; | |
| #undef M | |
| void SkLiteDL::draw(SkCanvas* canvas) const { | |
| SkAutoCanvasRestore acr(canvas, false); | |
| this->map(draw_fns, canvas, canvas->getTotalMatrix()); | |
| } | |
| SkLiteDL::~SkLiteDL() { | |
| this->reset(); | |
| } | |
| void SkLiteDL::reset() { | |
| this->map(dtor_fns); | |
| // Leave fBytes and fReserved alone. | |
| fUsed = 0; | |
| } |