blob: 227c2f30b6ea20ee851dffb305878ad39432d436 [file] [log] [blame]
mtklein9c5052f2016-08-06 12:51:51 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkCanvas.h"
mtklein29de8d92016-08-07 11:35:08 -07009#include "SkData.h"
reed6ae69692016-09-02 04:56:53 -070010#include "SkDrawFilter.h"
mtklein6f8411d2016-08-06 15:28:11 -070011#include "SkImageFilter.h"
mtklein9c5052f2016-08-06 12:51:51 -070012#include "SkLiteDL.h"
mtklein883c8ef2016-08-16 09:36:18 -070013#include "SkMath.h"
mtklein29de8d92016-08-07 11:35:08 -070014#include "SkPicture.h"
mtklein29de8d92016-08-07 11:35:08 -070015#include "SkRSXform.h"
mtkleinec559592016-08-06 20:31:30 -070016#include "SkTextBlob.h"
17
mtklein883c8ef2016-08-16 09:36:18 -070018#ifndef SKLITEDL_PAGE
19 #define SKLITEDL_PAGE 4096
20#endif
21
mtklein29de8d92016-08-07 11:35:08 -070022// A stand-in for an optional SkRect which was not set, e.g. bounds for a saveLayer().
mtklein3ff2cc82016-08-10 08:31:42 -070023static const SkRect kUnset = { SK_ScalarInfinity, 0,0,0};
mtklein29de8d92016-08-07 11:35:08 -070024static const SkRect* maybe_unset(const SkRect& r) {
mtklein3ff2cc82016-08-10 08:31:42 -070025 return r.left() == SK_ScalarInfinity ? nullptr : &r;
mtklein29de8d92016-08-07 11:35:08 -070026}
27
mtklein03591a72016-08-07 13:35:46 -070028// copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into dst.
29static void copy_v(void* dst) {}
mtkleinec559592016-08-06 20:31:30 -070030
mtklein03591a72016-08-07 13:35:46 -070031template <typename S, typename... Rest>
32static void copy_v(void* dst, const S* src, int n, Rest&&... rest) {
33 SkASSERTF(((uintptr_t)dst & (alignof(S)-1)) == 0,
34 "Expected %p to be aligned for at least %zu bytes.", dst, alignof(S));
35 sk_careful_memcpy(dst, src, n*sizeof(S));
36 copy_v(SkTAddOffset<void>(dst, n*sizeof(S)), std::forward<Rest>(rest)...);
mtkleinec559592016-08-06 20:31:30 -070037}
38
mtklein03591a72016-08-07 13:35:46 -070039// Helper for getting back at arrays which have been copy_v'd together after an Op.
mtklein29de8d92016-08-07 11:35:08 -070040template <typename D, typename T>
41static D* pod(T* op, size_t offset = 0) {
42 return SkTAddOffset<D>(op+1, offset);
43}
44
mtklein03591a72016-08-07 13:35:46 -070045// Pre-cache lazy non-threadsafe fields on SkPath and/or SkMatrix.
46static void make_threadsafe(SkPath* path, SkMatrix* matrix) {
mtkleindf0e3ec2016-09-02 06:51:57 -070047 if (path) { path->updateBoundsCache(); }
mtklein03591a72016-08-07 13:35:46 -070048 if (matrix) { (void)matrix->getType(); }
49}
50
mtklein9c5052f2016-08-06 12:51:51 -070051namespace {
mtkleind559eb22016-08-11 07:08:28 -070052#define TYPES(M) \
reed6ae69692016-09-02 04:56:53 -070053 M(SetDrawFilter) M(Save) M(Restore) M(SaveLayer) \
mtkleincbdf0072016-08-19 09:05:27 -070054 M(Concat) M(SetMatrix) M(Translate) M(TranslateZ) \
mtkleind559eb22016-08-11 07:08:28 -070055 M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \
msarett44df6512016-08-25 13:54:30 -070056 M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawRegion) M(DrawOval) M(DrawArc) \
57 M(DrawRRect) M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \
bsalomonac3aa242016-08-19 11:25:19 -070058 M(DrawShadowedPicture) \
mtkleind559eb22016-08-11 07:08:28 -070059 M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) \
60 M(DrawText) M(DrawPosText) M(DrawPosTextH) \
61 M(DrawTextOnPath) M(DrawTextRSXform) M(DrawTextBlob) \
62 M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas)
63
64#define M(T) T,
65 enum class Type : uint8_t { TYPES(M) };
66#undef M
67
mtklein9c5052f2016-08-06 12:51:51 -070068 struct Op {
mtklein91cd2802016-08-17 11:39:48 -070069 void makeThreadsafe() {}
mtklein9c5052f2016-08-06 12:51:51 -070070
mtkleind559eb22016-08-11 07:08:28 -070071 uint32_t type : 8;
72 uint32_t skip : 24;
mtklein9c5052f2016-08-06 12:51:51 -070073 };
mtkleind559eb22016-08-11 07:08:28 -070074 static_assert(sizeof(Op) == 4, "");
mtklein9c5052f2016-08-06 12:51:51 -070075
reed6ae69692016-09-02 04:56:53 -070076 struct SetDrawFilter final : Op {
77#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
78 static const auto kType = Type::SetDrawFilter;
79 SetDrawFilter(SkDrawFilter* df) : drawFilter(sk_ref_sp(df)) {}
80 sk_sp<SkDrawFilter> drawFilter;
81#endif
82 void draw(SkCanvas* c, const SkMatrix&) {
83#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
84 c->setDrawFilter(drawFilter.get());
85#endif
86 }
87 };
88
mtkleind559eb22016-08-11 07:08:28 -070089 struct Save final : Op {
90 static const auto kType = Type::Save;
mtklein64806192016-08-16 17:18:27 -070091 void draw(SkCanvas* c, const SkMatrix&) { c->save(); }
mtkleind559eb22016-08-11 07:08:28 -070092 };
93 struct Restore final : Op {
94 static const auto kType = Type::Restore;
mtklein64806192016-08-16 17:18:27 -070095 void draw(SkCanvas* c, const SkMatrix&) { c->restore(); }
mtkleind559eb22016-08-11 07:08:28 -070096 };
mtklein6f8411d2016-08-06 15:28:11 -070097 struct SaveLayer final : Op {
mtkleind559eb22016-08-11 07:08:28 -070098 static const auto kType = Type::SaveLayer;
mtklein6f8411d2016-08-06 15:28:11 -070099 SaveLayer(const SkRect* bounds, const SkPaint* paint,
mtklein29de8d92016-08-07 11:35:08 -0700100 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
mtklein6f8411d2016-08-06 15:28:11 -0700101 if (bounds) { this->bounds = *bounds; }
102 if (paint) { this->paint = *paint; }
103 this->backdrop = sk_ref_sp(backdrop);
104 this->flags = flags;
105 }
mtklein29de8d92016-08-07 11:35:08 -0700106 SkRect bounds = kUnset;
mtklein6f8411d2016-08-06 15:28:11 -0700107 SkPaint paint;
108 sk_sp<const SkImageFilter> backdrop;
mtklein29de8d92016-08-07 11:35:08 -0700109 SkCanvas::SaveLayerFlags flags;
mtklein64806192016-08-16 17:18:27 -0700110 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700111 c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags });
mtklein6f8411d2016-08-06 15:28:11 -0700112 }
113 };
mtklein9c5052f2016-08-06 12:51:51 -0700114
115 struct Concat final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700116 static const auto kType = Type::Concat;
mtklein9c5052f2016-08-06 12:51:51 -0700117 Concat(const SkMatrix& matrix) : matrix(matrix) {}
118 SkMatrix matrix;
mtklein64806192016-08-16 17:18:27 -0700119 void draw(SkCanvas* c, const SkMatrix&) { c->concat(matrix); }
mtkleind559eb22016-08-11 07:08:28 -0700120 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein9c5052f2016-08-06 12:51:51 -0700121 };
122 struct SetMatrix final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700123 static const auto kType = Type::SetMatrix;
mtklein9c5052f2016-08-06 12:51:51 -0700124 SetMatrix(const SkMatrix& matrix) : matrix(matrix) {}
125 SkMatrix matrix;
mtklein64806192016-08-16 17:18:27 -0700126 void draw(SkCanvas* c, const SkMatrix& original) {
127 c->setMatrix(SkMatrix::Concat(original, matrix));
128 }
mtkleind559eb22016-08-11 07:08:28 -0700129 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein9c5052f2016-08-06 12:51:51 -0700130 };
mtkleincbdf0072016-08-19 09:05:27 -0700131 struct Translate final : Op {
132 static const auto kType = Type::Translate;
133 Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
134 SkScalar dx,dy;
135 void draw(SkCanvas* c, const SkMatrix&) {
136 c->translate(dx, dy);
137 }
138 };
mtklein29de8d92016-08-07 11:35:08 -0700139 struct TranslateZ final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700140 static const auto kType = Type::TranslateZ;
mtklein29de8d92016-08-07 11:35:08 -0700141 TranslateZ(SkScalar dz) : dz(dz) {}
142 SkScalar dz;
mtklein64806192016-08-16 17:18:27 -0700143 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700144 #ifdef SK_EXPERIMENTAL_SHADOWING
145 c->translateZ(dz);
146 #endif
147 }
148 };
mtklein9c5052f2016-08-06 12:51:51 -0700149
mtklein6f8411d2016-08-06 15:28:11 -0700150 struct ClipPath final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700151 static const auto kType = Type::ClipPath;
mtklein6f8411d2016-08-06 15:28:11 -0700152 ClipPath(const SkPath& path, SkRegion::Op op, bool aa) : path(path), op(op), aa(aa) {}
153 SkPath path;
154 SkRegion::Op op;
155 bool aa;
mtklein64806192016-08-16 17:18:27 -0700156 void draw(SkCanvas* c, const SkMatrix&) { c->clipPath(path, op, aa); }
mtkleind559eb22016-08-11 07:08:28 -0700157 void makeThreadsafe() { make_threadsafe(&path, nullptr); }
mtklein6f8411d2016-08-06 15:28:11 -0700158 };
mtklein9c5052f2016-08-06 12:51:51 -0700159 struct ClipRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700160 static const auto kType = Type::ClipRect;
mtklein9c5052f2016-08-06 12:51:51 -0700161 ClipRect(const SkRect& rect, SkRegion::Op op, bool aa) : rect(rect), op(op), aa(aa) {}
162 SkRect rect;
163 SkRegion::Op op;
164 bool aa;
mtklein64806192016-08-16 17:18:27 -0700165 void draw(SkCanvas* c, const SkMatrix&) { c->clipRect(rect, op, aa); }
mtklein9c5052f2016-08-06 12:51:51 -0700166 };
mtklein6f8411d2016-08-06 15:28:11 -0700167 struct ClipRRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700168 static const auto kType = Type::ClipRRect;
mtklein6f8411d2016-08-06 15:28:11 -0700169 ClipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) : rrect(rrect), op(op), aa(aa) {}
170 SkRRect rrect;
171 SkRegion::Op op;
172 bool aa;
mtklein64806192016-08-16 17:18:27 -0700173 void draw(SkCanvas* c, const SkMatrix&) { c->clipRRect(rrect, op, aa); }
mtklein6f8411d2016-08-06 15:28:11 -0700174 };
175 struct ClipRegion final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700176 static const auto kType = Type::ClipRegion;
mtklein6f8411d2016-08-06 15:28:11 -0700177 ClipRegion(const SkRegion& region, SkRegion::Op op) : region(region), op(op) {}
178 SkRegion region;
179 SkRegion::Op op;
mtklein64806192016-08-16 17:18:27 -0700180 void draw(SkCanvas* c, const SkMatrix&) { c->clipRegion(region, op); }
mtklein6f8411d2016-08-06 15:28:11 -0700181 };
mtklein9c5052f2016-08-06 12:51:51 -0700182
mtklein6f8411d2016-08-06 15:28:11 -0700183 struct DrawPaint final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700184 static const auto kType = Type::DrawPaint;
mtklein6f8411d2016-08-06 15:28:11 -0700185 DrawPaint(const SkPaint& paint) : paint(paint) {}
186 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700187 void draw(SkCanvas* c, const SkMatrix&) { c->drawPaint(paint); }
mtklein6f8411d2016-08-06 15:28:11 -0700188 };
189 struct DrawPath final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700190 static const auto kType = Type::DrawPath;
mtklein6f8411d2016-08-06 15:28:11 -0700191 DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
192 SkPath path;
193 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700194 void draw(SkCanvas* c, const SkMatrix&) { c->drawPath(path, paint); }
mtkleind559eb22016-08-11 07:08:28 -0700195 void makeThreadsafe() { make_threadsafe(&path, nullptr); }
mtklein6f8411d2016-08-06 15:28:11 -0700196 };
mtklein9c5052f2016-08-06 12:51:51 -0700197 struct DrawRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700198 static const auto kType = Type::DrawRect;
mtklein9c5052f2016-08-06 12:51:51 -0700199 DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {}
200 SkRect rect;
201 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700202 void draw(SkCanvas* c, const SkMatrix&) { c->drawRect(rect, paint); }
mtklein9c5052f2016-08-06 12:51:51 -0700203 };
msarett44df6512016-08-25 13:54:30 -0700204 struct DrawRegion final : Op {
205 static const auto kType = Type::DrawRegion;
206 DrawRegion(const SkRegion& region, const SkPaint& paint) : region(region), paint(paint) {}
207 SkRegion region;
208 SkPaint paint;
209 void draw(SkCanvas* c, const SkMatrix&) { c->drawRegion(region, paint); }
210 };
mtklein6f8411d2016-08-06 15:28:11 -0700211 struct DrawOval final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700212 static const auto kType = Type::DrawOval;
mtklein6f8411d2016-08-06 15:28:11 -0700213 DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {}
214 SkRect oval;
mtklein9c5052f2016-08-06 12:51:51 -0700215 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700216 void draw(SkCanvas* c, const SkMatrix&) { c->drawOval(oval, paint); }
mtklein6f8411d2016-08-06 15:28:11 -0700217 };
bsalomonac3aa242016-08-19 11:25:19 -0700218 struct DrawArc final : Op {
219 static const auto kType = Type::DrawArc;
220 DrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
221 const SkPaint& paint)
222 : oval(oval), startAngle(startAngle), sweepAngle(sweepAngle), useCenter(useCenter)
223 , paint(paint) {}
224 SkRect oval;
225 SkScalar startAngle;
226 SkScalar sweepAngle;
227 bool useCenter;
228 SkPaint paint;
229 void draw(SkCanvas* c, const SkMatrix&) { c->drawArc(oval, startAngle, sweepAngle,
230 useCenter, paint); }
231 };
mtklein6f8411d2016-08-06 15:28:11 -0700232 struct DrawRRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700233 static const auto kType = Type::DrawRRect;
mtklein6f8411d2016-08-06 15:28:11 -0700234 DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {}
235 SkRRect rrect;
236 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700237 void draw(SkCanvas* c, const SkMatrix&) { c->drawRRect(rrect, paint); }
mtklein6f8411d2016-08-06 15:28:11 -0700238 };
239 struct DrawDRRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700240 static const auto kType = Type::DrawDRRect;
mtklein6f8411d2016-08-06 15:28:11 -0700241 DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
242 : outer(outer), inner(inner), paint(paint) {}
243 SkRRect outer, inner;
244 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700245 void draw(SkCanvas* c, const SkMatrix&) { c->drawDRRect(outer, inner, paint); }
mtklein9c5052f2016-08-06 12:51:51 -0700246 };
247
mtklein29de8d92016-08-07 11:35:08 -0700248 struct DrawAnnotation final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700249 static const auto kType = Type::DrawAnnotation;
mtklein29de8d92016-08-07 11:35:08 -0700250 DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {}
251 SkRect rect;
252 sk_sp<SkData> value;
mtklein64806192016-08-16 17:18:27 -0700253 void draw(SkCanvas* c, const SkMatrix&) {
254 c->drawAnnotation(rect, pod<char>(this), value.get());
255 }
mtklein29de8d92016-08-07 11:35:08 -0700256 };
257 struct DrawDrawable final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700258 static const auto kType = Type::DrawDrawable;
mtklein29de8d92016-08-07 11:35:08 -0700259 DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) {
260 if (matrix) { this->matrix = *matrix; }
261 }
mtklein03591a72016-08-07 13:35:46 -0700262 sk_sp<SkDrawable> drawable;
263 sk_sp<const SkPicture> snapped;
264 SkMatrix matrix = SkMatrix::I();
mtklein64806192016-08-16 17:18:27 -0700265 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700266 snapped ? c->drawPicture(snapped.get(), &matrix, nullptr)
267 : c->drawDrawable(drawable.get(), &matrix);
268 }
mtkleind559eb22016-08-11 07:08:28 -0700269 void makeThreadsafe() {
mtklein03591a72016-08-07 13:35:46 -0700270 snapped.reset(drawable->newPictureSnapshot());
271 make_threadsafe(nullptr, &matrix);
272 }
mtklein29de8d92016-08-07 11:35:08 -0700273 };
274 struct DrawPicture final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700275 static const auto kType = Type::DrawPicture;
mtklein29de8d92016-08-07 11:35:08 -0700276 DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
277 : picture(sk_ref_sp(picture)) {
278 if (matrix) { this->matrix = *matrix; }
mtklein03591a72016-08-07 13:35:46 -0700279 if (paint) { this->paint = *paint; has_paint = true; }
mtklein29de8d92016-08-07 11:35:08 -0700280 }
281 sk_sp<const SkPicture> picture;
282 SkMatrix matrix = SkMatrix::I();
283 SkPaint paint;
mtklein03591a72016-08-07 13:35:46 -0700284 bool has_paint = false; // TODO: why is a default paint not the same?
mtklein64806192016-08-16 17:18:27 -0700285 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700286 c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr);
287 }
mtkleind559eb22016-08-11 07:08:28 -0700288 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein29de8d92016-08-07 11:35:08 -0700289 };
290 struct DrawShadowedPicture final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700291 static const auto kType = Type::DrawShadowedPicture;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700292 DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix,
293 const SkPaint* paint, const SkShadowParams& params)
mtklein29de8d92016-08-07 11:35:08 -0700294 : picture(sk_ref_sp(picture)) {
295 if (matrix) { this->matrix = *matrix; }
296 if (paint) { this->paint = *paint; }
vjiaoblacke6f5d562016-08-25 06:30:23 -0700297 this->params = params;
mtklein29de8d92016-08-07 11:35:08 -0700298 }
299 sk_sp<const SkPicture> picture;
300 SkMatrix matrix = SkMatrix::I();
301 SkPaint paint;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700302 SkShadowParams params;
mtklein64806192016-08-16 17:18:27 -0700303 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700304 #ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke6f5d562016-08-25 06:30:23 -0700305 c->drawShadowedPicture(picture.get(), &matrix, &paint, params);
mtklein29de8d92016-08-07 11:35:08 -0700306 #endif
307 }
mtkleind559eb22016-08-11 07:08:28 -0700308 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein29de8d92016-08-07 11:35:08 -0700309 };
310
mtkleinec559592016-08-06 20:31:30 -0700311 struct DrawImage final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700312 static const auto kType = Type::DrawImage;
mtkleinec559592016-08-06 20:31:30 -0700313 DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700314 : image(std::move(image)), x(x), y(y) {
mtkleinec559592016-08-06 20:31:30 -0700315 if (paint) { this->paint = *paint; }
mtklein9c5052f2016-08-06 12:51:51 -0700316 }
mtkleinec559592016-08-06 20:31:30 -0700317 sk_sp<const SkImage> image;
318 SkScalar x,y;
319 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700320 void draw(SkCanvas* c, const SkMatrix&) { c->drawImage(image.get(), x,y, &paint); }
mtkleinec559592016-08-06 20:31:30 -0700321 };
322 struct DrawImageNine final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700323 static const auto kType = Type::DrawImageNine;
mtkleinec559592016-08-06 20:31:30 -0700324 DrawImageNine(sk_sp<const SkImage>&& image,
325 const SkIRect& center, const SkRect& dst, const SkPaint* paint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700326 : image(std::move(image)), center(center), dst(dst) {
mtkleinec559592016-08-06 20:31:30 -0700327 if (paint) { this->paint = *paint; }
328 }
329 sk_sp<const SkImage> image;
330 SkIRect center;
331 SkRect dst;
332 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700333 void draw(SkCanvas* c, const SkMatrix&) {
334 c->drawImageNine(image.get(), center, dst, &paint);
335 }
mtkleinec559592016-08-06 20:31:30 -0700336 };
337 struct DrawImageRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700338 static const auto kType = Type::DrawImageRect;
mtkleinec559592016-08-06 20:31:30 -0700339 DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
340 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700341 : image(std::move(image)), dst(dst), constraint(constraint) {
mtkleinec559592016-08-06 20:31:30 -0700342 this->src = src ? *src : SkRect::MakeIWH(image->width(), image->height());
343 if (paint) { this->paint = *paint; }
344 }
345 sk_sp<const SkImage> image;
346 SkRect src, dst;
347 SkPaint paint;
348 SkCanvas::SrcRectConstraint constraint;
mtklein64806192016-08-16 17:18:27 -0700349 void draw(SkCanvas* c, const SkMatrix&) {
mtkleinec559592016-08-06 20:31:30 -0700350 c->drawImageRect(image.get(), src, dst, &paint, constraint);
351 }
mtkleinec559592016-08-06 20:31:30 -0700352 };
mtklein29de8d92016-08-07 11:35:08 -0700353 struct DrawImageLattice final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700354 static const auto kType = Type::DrawImageLattice;
msarett0764efe2016-09-02 11:24:30 -0700355 DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs,
mtklein29de8d92016-08-07 11:35:08 -0700356 const SkRect& dst, const SkPaint* paint)
msarett0764efe2016-09-02 11:24:30 -0700357 : image(std::move(image)), xs(xs), ys(ys), fs(fs), dst(dst) {
mtklein29de8d92016-08-07 11:35:08 -0700358 if (paint) { this->paint = *paint; }
359 }
360 sk_sp<const SkImage> image;
msarett0764efe2016-09-02 11:24:30 -0700361 int xs, ys, fs;
mtklein29de8d92016-08-07 11:35:08 -0700362 SkRect dst;
363 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700364 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700365 auto xdivs = pod<int>(this, 0),
366 ydivs = pod<int>(this, xs*sizeof(int));
msarett0764efe2016-09-02 11:24:30 -0700367 auto flags = (0 == fs) ? nullptr :
368 pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int));
369 c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys}, dst, &paint);
mtklein29de8d92016-08-07 11:35:08 -0700370 }
mtklein29de8d92016-08-07 11:35:08 -0700371 };
mtkleinec559592016-08-06 20:31:30 -0700372
373 struct DrawText final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700374 static const auto kType = Type::DrawText;
mtkleinec559592016-08-06 20:31:30 -0700375 DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint)
376 : bytes(bytes), x(x), y(y), paint(paint) {}
377 size_t bytes;
378 SkScalar x,y;
379 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700380 void draw(SkCanvas* c, const SkMatrix&) {
381 c->drawText(pod<void>(this), bytes, x,y, paint);
382 }
mtkleinec559592016-08-06 20:31:30 -0700383 };
384 struct DrawPosText final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700385 static const auto kType = Type::DrawPosText;
mtklein03591a72016-08-07 13:35:46 -0700386 DrawPosText(size_t bytes, const SkPaint& paint, int n)
387 : bytes(bytes), paint(paint), n(n) {}
mtkleinec559592016-08-06 20:31:30 -0700388 size_t bytes;
389 SkPaint paint;
mtklein03591a72016-08-07 13:35:46 -0700390 int n;
mtklein64806192016-08-16 17:18:27 -0700391 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700392 auto points = pod<SkPoint>(this);
393 auto text = pod<void>(this, n*sizeof(SkPoint));
394 c->drawPosText(text, bytes, points, paint);
mtkleinec559592016-08-06 20:31:30 -0700395 }
mtkleinec559592016-08-06 20:31:30 -0700396 };
397 struct DrawPosTextH final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700398 static const auto kType = Type::DrawPosTextH;
mtklein03591a72016-08-07 13:35:46 -0700399 DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n)
400 : bytes(bytes), y(y), paint(paint), n(n) {}
mtklein29de8d92016-08-07 11:35:08 -0700401 size_t bytes;
mtkleinec559592016-08-06 20:31:30 -0700402 SkScalar y;
mtklein29de8d92016-08-07 11:35:08 -0700403 SkPaint paint;
mtklein03591a72016-08-07 13:35:46 -0700404 int n;
mtklein64806192016-08-16 17:18:27 -0700405 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700406 auto xs = pod<SkScalar>(this);
407 auto text = pod<void>(this, n*sizeof(SkScalar));
408 c->drawPosTextH(text, bytes, xs, y, paint);
mtklein29de8d92016-08-07 11:35:08 -0700409 }
mtklein29de8d92016-08-07 11:35:08 -0700410 };
411 struct DrawTextOnPath final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700412 static const auto kType = Type::DrawTextOnPath;
mtklein29de8d92016-08-07 11:35:08 -0700413 DrawTextOnPath(size_t bytes, const SkPath& path,
414 const SkMatrix* matrix, const SkPaint& paint)
415 : bytes(bytes), path(path), paint(paint) {
416 if (matrix) { this->matrix = *matrix; }
417 }
418 size_t bytes;
419 SkPath path;
420 SkMatrix matrix = SkMatrix::I();
421 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700422 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700423 c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint);
424 }
mtkleind559eb22016-08-11 07:08:28 -0700425 void makeThreadsafe() { make_threadsafe(&path, &matrix); }
mtklein29de8d92016-08-07 11:35:08 -0700426 };
427 struct DrawTextRSXform final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700428 static const auto kType = Type::DrawTextRSXform;
mtklein29de8d92016-08-07 11:35:08 -0700429 DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint)
430 : bytes(bytes), paint(paint) {
431 if (cull) { this->cull = *cull; }
432 }
433 size_t bytes;
434 SkRect cull = kUnset;
mtkleinec559592016-08-06 20:31:30 -0700435 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700436 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700437 c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes),
438 maybe_unset(cull), paint);
mtkleinec559592016-08-06 20:31:30 -0700439 }
mtkleinec559592016-08-06 20:31:30 -0700440 };
441 struct DrawTextBlob final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700442 static const auto kType = Type::DrawTextBlob;
mtkleinec559592016-08-06 20:31:30 -0700443 DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
444 : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
445 sk_sp<const SkTextBlob> blob;
446 SkScalar x,y;
447 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700448 void draw(SkCanvas* c, const SkMatrix&) {
449 c->drawTextBlob(blob.get(), x,y, paint);
450 }
mtkleinec559592016-08-06 20:31:30 -0700451 };
mtklein29de8d92016-08-07 11:35:08 -0700452
mtklein03591a72016-08-07 13:35:46 -0700453 struct DrawPatch final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700454 static const auto kType = Type::DrawPatch;
mtklein03591a72016-08-07 13:35:46 -0700455 DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
456 SkXfermode* xfermode, const SkPaint& paint)
457 : xfermode(sk_ref_sp(xfermode)), paint(paint) {
458 copy_v(this->cubics, cubics, 12);
459 if (colors) { copy_v(this->colors, colors, 4); has_colors = true; }
460 if (texs ) { copy_v(this->texs , texs , 4); has_texs = true; }
461 }
462 SkPoint cubics[12];
463 SkColor colors[4];
464 SkPoint texs[4];
465 sk_sp<SkXfermode> xfermode;
466 SkPaint paint;
467 bool has_colors = false;
468 bool has_texs = false;
mtklein64806192016-08-16 17:18:27 -0700469 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700470 c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr,
471 xfermode.get(), paint);
472 }
mtklein03591a72016-08-07 13:35:46 -0700473 };
mtklein29de8d92016-08-07 11:35:08 -0700474 struct DrawPoints final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700475 static const auto kType = Type::DrawPoints;
mtklein29de8d92016-08-07 11:35:08 -0700476 DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint)
477 : mode(mode), count(count), paint(paint) {}
478 SkCanvas::PointMode mode;
479 size_t count;
480 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700481 void draw(SkCanvas* c, const SkMatrix&) {
482 c->drawPoints(mode, count, pod<SkPoint>(this), paint);
483 }
mtklein29de8d92016-08-07 11:35:08 -0700484 };
mtklein03591a72016-08-07 13:35:46 -0700485 struct DrawVertices final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700486 static const auto kType = Type::DrawVertices;
mtklein03591a72016-08-07 13:35:46 -0700487 DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices,
488 const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices)
489 : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices)
490 , paint(paint), has_texs(has_texs), has_colors(has_colors), has_indices(has_indices) {}
491 SkCanvas::VertexMode mode;
492 int count;
493 sk_sp<SkXfermode> xfermode;
494 int nindices;
495 SkPaint paint;
496 bool has_texs;
497 bool has_colors;
498 bool has_indices;
mtklein64806192016-08-16 17:18:27 -0700499 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700500 SkPoint* vertices = pod<SkPoint>(this, 0);
501 size_t offset = count*sizeof(SkPoint);
502
503 SkPoint* texs = nullptr;
504 if (has_texs) {
505 texs = pod<SkPoint>(this, offset);
506 offset += count*sizeof(SkPoint);
507 }
508
509 SkColor* colors = nullptr;
510 if (has_colors) {
511 colors = pod<SkColor>(this, offset);
512 offset += count*sizeof(SkColor);
513 }
514
515 uint16_t* indices = nullptr;
516 if (has_indices) {
517 indices = pod<uint16_t>(this, offset);
518 }
519 c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(),
520 indices, nindices, paint);
521 }
mtklein03591a72016-08-07 13:35:46 -0700522 };
mtklein29de8d92016-08-07 11:35:08 -0700523 struct DrawAtlas final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700524 static const auto kType = Type::DrawAtlas;
mtklein29de8d92016-08-07 11:35:08 -0700525 DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode,
526 const SkRect* cull, const SkPaint* paint, bool has_colors)
527 : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) {
528 if (cull) { this->cull = *cull; }
529 if (paint) { this->paint = *paint; }
530 }
531 sk_sp<const SkImage> atlas;
532 int count;
533 SkXfermode::Mode xfermode;
534 SkRect cull = kUnset;
535 SkPaint paint;
536 bool has_colors;
mtklein64806192016-08-16 17:18:27 -0700537 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700538 auto xforms = pod<SkRSXform>(this, 0);
539 auto texs = pod<SkRect>(this, count*sizeof(SkRSXform));
540 auto colors = has_colors
541 ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect)))
542 : nullptr;
543 c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode,
544 maybe_unset(cull), &paint);
545 }
mtklein29de8d92016-08-07 11:35:08 -0700546 };
mtkleinec559592016-08-06 20:31:30 -0700547}
548
549template <typename T, typename... Args>
mtkleinb2028332016-08-09 15:13:18 -0700550void* SkLiteDL::push(size_t pod, Args&&... args) {
mtkleinec559592016-08-06 20:31:30 -0700551 size_t skip = SkAlignPtr(sizeof(T) + pod);
mtkleind559eb22016-08-11 07:08:28 -0700552 SkASSERT(skip < (1<<24));
mtkleinb2028332016-08-09 15:13:18 -0700553 if (fUsed + skip > fReserved) {
mtklein883c8ef2016-08-16 09:36:18 -0700554 static_assert(SkIsPow2(SKLITEDL_PAGE), "This math needs updating for non-pow2.");
555 // Next greater multiple of SKLITEDL_PAGE.
556 fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE-1);
mtkleinb2028332016-08-09 15:13:18 -0700557 fBytes.realloc(fReserved);
558 }
559 SkASSERT(fUsed + skip <= fReserved);
560 auto op = (T*)(fBytes.get() + fUsed);
561 fUsed += skip;
mtkleinec559592016-08-06 20:31:30 -0700562 new (op) T{ std::forward<Args>(args)... };
mtkleind559eb22016-08-11 07:08:28 -0700563 op->type = (uint32_t)T::kType;
mtkleinec559592016-08-06 20:31:30 -0700564 op->skip = skip;
565 return op+1;
566}
567
mtklein64806192016-08-16 17:18:27 -0700568template <typename Fn, typename... Args>
569inline void SkLiteDL::map(const Fn fns[], Args... args) {
mtkleinb2028332016-08-09 15:13:18 -0700570 auto end = fBytes.get() + fUsed;
571 for (uint8_t* ptr = fBytes.get(); ptr < end; ) {
mtkleinec559592016-08-06 20:31:30 -0700572 auto op = (Op*)ptr;
mtkleind559eb22016-08-11 07:08:28 -0700573 auto type = op->type;
574 auto skip = op->skip;
575 if (auto fn = fns[type]) { // We replace no-op functions with nullptrs
576 fn(op, args...); // to avoid the overhead of a pointless call.
577 }
578 ptr += skip;
mtklein9c5052f2016-08-06 12:51:51 -0700579 }
580}
581
reed6ae69692016-09-02 04:56:53 -0700582#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
583void SkLiteDL::setDrawFilter(SkDrawFilter* df) {
584 this->push<SetDrawFilter>(0, df);
585}
586#endif
587
mtkleinb2028332016-08-09 15:13:18 -0700588void SkLiteDL:: save() { this->push <Save>(0); }
589void SkLiteDL::restore() { this->push<Restore>(0); }
mtklein6f8411d2016-08-06 15:28:11 -0700590void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint,
mtklein29de8d92016-08-07 11:35:08 -0700591 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
mtkleinb2028332016-08-09 15:13:18 -0700592 this->push<SaveLayer>(0, bounds, paint, backdrop, flags);
mtklein6f8411d2016-08-06 15:28:11 -0700593}
mtklein9c5052f2016-08-06 12:51:51 -0700594
mtkleincbdf0072016-08-19 09:05:27 -0700595void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); }
596void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); }
597void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); }
mtkleinb2028332016-08-09 15:13:18 -0700598void SkLiteDL::translateZ(SkScalar dz) { this->push<TranslateZ>(0, dz); }
mtklein9c5052f2016-08-06 12:51:51 -0700599
mtklein6f8411d2016-08-06 15:28:11 -0700600void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) {
mtkleinb2028332016-08-09 15:13:18 -0700601 this->push<ClipPath>(0, path, op, aa);
mtklein6f8411d2016-08-06 15:28:11 -0700602}
mtklein9c5052f2016-08-06 12:51:51 -0700603void SkLiteDL::clipRect(const SkRect& rect, SkRegion::Op op, bool aa) {
mtkleinb2028332016-08-09 15:13:18 -0700604 this->push<ClipRect>(0, rect, op, aa);
mtklein9c5052f2016-08-06 12:51:51 -0700605}
mtklein6f8411d2016-08-06 15:28:11 -0700606void SkLiteDL::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) {
mtkleinb2028332016-08-09 15:13:18 -0700607 this->push<ClipRRect>(0, rrect, op, aa);
mtklein6f8411d2016-08-06 15:28:11 -0700608}
609void SkLiteDL::clipRegion(const SkRegion& region, SkRegion::Op op) {
mtkleinb2028332016-08-09 15:13:18 -0700610 this->push<ClipRegion>(0, region, op);
mtklein6f8411d2016-08-06 15:28:11 -0700611}
mtklein9c5052f2016-08-06 12:51:51 -0700612
mtklein6f8411d2016-08-06 15:28:11 -0700613void SkLiteDL::drawPaint(const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700614 this->push<DrawPaint>(0, paint);
mtklein9c5052f2016-08-06 12:51:51 -0700615}
616void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700617 this->push<DrawPath>(0, path, paint);
mtklein9c5052f2016-08-06 12:51:51 -0700618}
mtklein6f8411d2016-08-06 15:28:11 -0700619void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700620 this->push<DrawRect>(0, rect, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700621}
msarett44df6512016-08-25 13:54:30 -0700622void SkLiteDL::drawRegion(const SkRegion& region, const SkPaint& paint) {
623 this->push<DrawRegion>(0, region, paint);
624}
mtklein6f8411d2016-08-06 15:28:11 -0700625void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700626 this->push<DrawOval>(0, oval, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700627}
bsalomonac3aa242016-08-19 11:25:19 -0700628void SkLiteDL::drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
629 const SkPaint& paint) {
630 this->push<DrawArc>(0, oval, startAngle, sweepAngle, useCenter, paint);
631}
mtklein6f8411d2016-08-06 15:28:11 -0700632void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700633 this->push<DrawRRect>(0, rrect, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700634}
635void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700636 this->push<DrawDRRect>(0, outer, inner, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700637}
mtklein9c5052f2016-08-06 12:51:51 -0700638
mtklein29de8d92016-08-07 11:35:08 -0700639void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) {
640 size_t bytes = strlen(key)+1;
mtkleinb2028332016-08-09 15:13:18 -0700641 void* pod = this->push<DrawAnnotation>(bytes, rect, value);
mtklein03591a72016-08-07 13:35:46 -0700642 copy_v(pod, key,bytes);
mtklein29de8d92016-08-07 11:35:08 -0700643}
644void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
mtkleinb2028332016-08-09 15:13:18 -0700645 this->push<DrawDrawable>(0, drawable, matrix);
mtklein29de8d92016-08-07 11:35:08 -0700646}
647void SkLiteDL::drawPicture(const SkPicture* picture,
648 const SkMatrix* matrix, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700649 this->push<DrawPicture>(0, picture, matrix, paint);
mtklein29de8d92016-08-07 11:35:08 -0700650}
vjiaoblacke6f5d562016-08-25 06:30:23 -0700651void SkLiteDL::drawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix,
652 const SkPaint* paint, const SkShadowParams& params) {
653 push<DrawShadowedPicture>(0, picture, matrix, paint, params);
mtklein29de8d92016-08-07 11:35:08 -0700654}
655
mtkleinec559592016-08-06 20:31:30 -0700656void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700657 this->push<DrawImage>(0, SkImage::MakeFromBitmap(bm), x,y, paint);
mtkleinec559592016-08-06 20:31:30 -0700658}
659void SkLiteDL::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
660 const SkRect& dst, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700661 this->push<DrawImageNine>(0, SkImage::MakeFromBitmap(bm), center, dst, paint);
mtkleinec559592016-08-06 20:31:30 -0700662}
663void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
664 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
mtkleinb2028332016-08-09 15:13:18 -0700665 this->push<DrawImageRect>(0, SkImage::MakeFromBitmap(bm), src, dst, paint, constraint);
mtkleinec559592016-08-06 20:31:30 -0700666}
msarett16882062016-08-16 09:31:08 -0700667void SkLiteDL::drawBitmapLattice(const SkBitmap& bm, const SkCanvas::Lattice& lattice,
668 const SkRect& dst, const SkPaint* paint) {
669 int xs = lattice.fXCount, ys = lattice.fYCount;
msarett0764efe2016-09-02 11:24:30 -0700670 int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0;
671 size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags);
672 void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, fs, dst,
msarett16882062016-08-16 09:31:08 -0700673 paint);
674 copy_v(pod, lattice.fXDivs, xs,
msarett0764efe2016-09-02 11:24:30 -0700675 lattice.fYDivs, ys,
676 lattice.fFlags, fs);
msarett16882062016-08-16 09:31:08 -0700677}
mtkleinec559592016-08-06 20:31:30 -0700678
679void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700680 this->push<DrawImage>(0, sk_ref_sp(image), x,y, paint);
mtkleinec559592016-08-06 20:31:30 -0700681}
682void SkLiteDL::drawImageNine(const SkImage* image, const SkIRect& center,
683 const SkRect& dst, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700684 this->push<DrawImageNine>(0, sk_ref_sp(image), center, dst, paint);
mtkleinec559592016-08-06 20:31:30 -0700685}
686void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
687 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
mtkleinb2028332016-08-09 15:13:18 -0700688 this->push<DrawImageRect>(0, sk_ref_sp(image), src, dst, paint, constraint);
mtkleinec559592016-08-06 20:31:30 -0700689}
mtklein29de8d92016-08-07 11:35:08 -0700690void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
691 const SkRect& dst, const SkPaint* paint) {
692 int xs = lattice.fXCount, ys = lattice.fYCount;
msarett0764efe2016-09-02 11:24:30 -0700693 int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0;
694 size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags);
695 void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, fs, dst, paint);
mtklein03591a72016-08-07 13:35:46 -0700696 copy_v(pod, lattice.fXDivs, xs,
msarett0764efe2016-09-02 11:24:30 -0700697 lattice.fYDivs, ys,
698 lattice.fFlags, fs);
mtklein29de8d92016-08-07 11:35:08 -0700699}
mtkleinec559592016-08-06 20:31:30 -0700700
701void SkLiteDL::drawText(const void* text, size_t bytes,
702 SkScalar x, SkScalar y, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700703 void* pod = this->push<DrawText>(bytes, bytes, x, y, paint);
mtklein03591a72016-08-07 13:35:46 -0700704 copy_v(pod, (const char*)text,bytes);
mtkleinec559592016-08-06 20:31:30 -0700705}
706void SkLiteDL::drawPosText(const void* text, size_t bytes,
707 const SkPoint pos[], const SkPaint& paint) {
708 int n = paint.countText(text, bytes);
mtkleinb2028332016-08-09 15:13:18 -0700709 void* pod = this->push<DrawPosText>(n*sizeof(SkPoint)+bytes, bytes, paint, n);
mtklein03591a72016-08-07 13:35:46 -0700710 copy_v(pod, pos,n, (const char*)text,bytes);
mtkleinec559592016-08-06 20:31:30 -0700711}
712void SkLiteDL::drawPosTextH(const void* text, size_t bytes,
713 const SkScalar xs[], SkScalar y, const SkPaint& paint) {
714 int n = paint.countText(text, bytes);
mtkleinb2028332016-08-09 15:13:18 -0700715 void* pod = this->push<DrawPosTextH>(n*sizeof(SkScalar)+bytes, bytes, y, paint, n);
mtklein03591a72016-08-07 13:35:46 -0700716 copy_v(pod, xs,n, (const char*)text,bytes);
mtkleinec559592016-08-06 20:31:30 -0700717}
mtklein29de8d92016-08-07 11:35:08 -0700718void SkLiteDL::drawTextOnPath(const void* text, size_t bytes,
719 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700720 void* pod = this->push<DrawTextOnPath>(bytes, bytes, path, matrix, paint);
mtklein03591a72016-08-07 13:35:46 -0700721 copy_v(pod, (const char*)text,bytes);
mtklein29de8d92016-08-07 11:35:08 -0700722}
723void SkLiteDL::drawTextRSXform(const void* text, size_t bytes,
724 const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) {
725 int n = paint.countText(text, bytes);
mtkleinb2028332016-08-09 15:13:18 -0700726 void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, cull, paint);
mtklein03591a72016-08-07 13:35:46 -0700727 copy_v(pod, (const char*)text,bytes, xforms,n);
mtklein29de8d92016-08-07 11:35:08 -0700728}
mtkleinec559592016-08-06 20:31:30 -0700729void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700730 this->push<DrawTextBlob>(0, blob, x,y, paint);
mtkleinec559592016-08-06 20:31:30 -0700731}
732
mtklein03591a72016-08-07 13:35:46 -0700733void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4],
734 SkXfermode* xfermode, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700735 this->push<DrawPatch>(0, points, colors, texs, xfermode, paint);
mtklein03591a72016-08-07 13:35:46 -0700736}
mtklein29de8d92016-08-07 11:35:08 -0700737void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[],
738 const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700739 void* pod = this->push<DrawPoints>(count*sizeof(SkPoint), mode, count, paint);
mtklein03591a72016-08-07 13:35:46 -0700740 copy_v(pod, points,count);
741}
742void SkLiteDL::drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[],
743 const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode,
744 const uint16_t indices[], int nindices, const SkPaint& paint) {
745 size_t bytes = count * sizeof(SkPoint);
746 if (texs ) { bytes += count * sizeof(SkPoint); }
747 if (colors) { bytes += count * sizeof(SkColor); }
748 if (indices) { bytes += nindices * sizeof(uint16_t); }
mtkleinb2028332016-08-09 15:13:18 -0700749 void* pod = this->push<DrawVertices>(bytes, mode, count, xfermode, nindices, paint,
750 texs != nullptr, colors != nullptr, indices != nullptr);
mtklein03591a72016-08-07 13:35:46 -0700751 copy_v(pod, vertices, count,
752 texs, texs ? count : 0,
753 colors, colors ? count : 0,
754 indices, indices ? nindices : 0);
mtklein29de8d92016-08-07 11:35:08 -0700755}
756void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
757 const SkColor colors[], int count, SkXfermode::Mode xfermode,
758 const SkRect* cull, const SkPaint* paint) {
759 size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect));
760 if (colors) {
761 bytes += count*sizeof(SkColor);
762 }
mtkleinb2028332016-08-09 15:13:18 -0700763 void* pod = this->push<DrawAtlas>(bytes,
764 atlas, count, xfermode, cull, paint, colors != nullptr);
mtklein03591a72016-08-07 13:35:46 -0700765 copy_v(pod, xforms, count,
766 texs, count,
767 colors, colors ? count : 0);
mtklein29de8d92016-08-07 11:35:08 -0700768}
769
mtklein91cd2802016-08-17 11:39:48 -0700770typedef void(*draw_fn)(void*, SkCanvas*, const SkMatrix&);
771typedef void(*void_fn)(void*);
mtkleinec559592016-08-06 20:31:30 -0700772
mtkleind559eb22016-08-11 07:08:28 -0700773// All ops implement draw().
mtklein64806192016-08-16 17:18:27 -0700774#define M(T) [](void* op, SkCanvas* c, const SkMatrix& original) { ((T*)op)->draw(c, original); },
775static const draw_fn draw_fns[] = { TYPES(M) };
mtkleind559eb22016-08-11 07:08:28 -0700776#undef M
mtklein9c5052f2016-08-06 12:51:51 -0700777
mtklein91cd2802016-08-17 11:39:48 -0700778#define M(T) [](void* op) { ((T*)op)->makeThreadsafe(); },
mtkleind559eb22016-08-11 07:08:28 -0700779static const void_fn make_threadsafe_fns[] = { TYPES(M) };
780#undef M
781
782// Older libstdc++ has pre-standard std::has_trivial_destructor.
783#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000)
784 template <typename T> using can_skip_destructor = std::has_trivial_destructor<T>;
785#else
786 template <typename T> using can_skip_destructor = std::is_trivially_destructible<T>;
787#endif
788
789// Most state ops (matrix, clip, save, restore) have a trivial destructor.
790#define M(T) !can_skip_destructor<T>::value ? [](void* op) { ((T*)op)->~T(); } : (void_fn)nullptr,
791static const void_fn dtor_fns[] = { TYPES(M) };
792#undef M
793
mtklein91cd2802016-08-17 11:39:48 -0700794void SkLiteDL::onDraw(SkCanvas* canvas) { this->map(draw_fns, canvas, canvas->getTotalMatrix()); }
795void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); }
mtklein03591a72016-08-07 13:35:46 -0700796
mtklein9c5052f2016-08-06 12:51:51 -0700797SkRect SkLiteDL::onGetBounds() {
798 return fBounds;
799}
800
mtklein883c8ef2016-08-16 09:36:18 -0700801SkLiteDL:: SkLiteDL(SkRect bounds) : fUsed(0), fReserved(0), fBounds(bounds) {}
mtklein765b6e62016-08-08 12:23:02 -0700802
mtklein883c8ef2016-08-16 09:36:18 -0700803SkLiteDL::~SkLiteDL() {
804 this->reset(SkRect::MakeEmpty());
805}
mtklein9c5052f2016-08-06 12:51:51 -0700806
807sk_sp<SkLiteDL> SkLiteDL::New(SkRect bounds) {
mtklein883c8ef2016-08-16 09:36:18 -0700808 return sk_sp<SkLiteDL>(new SkLiteDL(bounds));
mtklein9c5052f2016-08-06 12:51:51 -0700809}
810
mtklein883c8ef2016-08-16 09:36:18 -0700811void SkLiteDL::reset(SkRect bounds) {
812 SkASSERT(this->unique());
813 this->map(dtor_fns);
mtklein9c5052f2016-08-06 12:51:51 -0700814
mtklein883c8ef2016-08-16 09:36:18 -0700815 // Leave fBytes and fReserved alone.
816 fUsed = 0;
817 fBounds = bounds;
mtklein0c753e52016-08-09 07:40:23 -0700818}
mtkleinf53fcc82016-09-08 08:49:08 -0700819
820void SkLiteDL::drawAsLayer(SkCanvas* canvas, const SkMatrix* matrix, const SkPaint* paint) {
821 auto fallback_plan = [&] {
822 SkRect bounds = this->getBounds();
823 canvas->saveLayer(&bounds, paint);
824 this->draw(canvas, matrix);
825 canvas->restore();
826 };
827
828 // TODO: single-draw specializations
829
830 return fallback_plan();
831}