blob: c3bf976a888d61e6abaac0293ccfc06fa26282d1 [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"
mtklein6f8411d2016-08-06 15:28:11 -070010#include "SkImageFilter.h"
mtklein9c5052f2016-08-06 12:51:51 -070011#include "SkLiteDL.h"
mtklein883c8ef2016-08-16 09:36:18 -070012#include "SkMath.h"
mtklein29de8d92016-08-07 11:35:08 -070013#include "SkPicture.h"
mtklein9c5052f2016-08-06 12:51:51 -070014#include "SkMutex.h"
mtklein29de8d92016-08-07 11:35:08 -070015#include "SkRSXform.h"
mtklein9c5052f2016-08-06 12:51:51 -070016#include "SkSpinlock.h"
mtkleinec559592016-08-06 20:31:30 -070017#include "SkTextBlob.h"
18
mtklein883c8ef2016-08-16 09:36:18 -070019#ifndef SKLITEDL_PAGE
20 #define SKLITEDL_PAGE 4096
21#endif
22
mtklein29de8d92016-08-07 11:35:08 -070023// A stand-in for an optional SkRect which was not set, e.g. bounds for a saveLayer().
mtklein3ff2cc82016-08-10 08:31:42 -070024static const SkRect kUnset = { SK_ScalarInfinity, 0,0,0};
mtklein29de8d92016-08-07 11:35:08 -070025static const SkRect* maybe_unset(const SkRect& r) {
mtklein3ff2cc82016-08-10 08:31:42 -070026 return r.left() == SK_ScalarInfinity ? nullptr : &r;
mtklein29de8d92016-08-07 11:35:08 -070027}
28
mtklein03591a72016-08-07 13:35:46 -070029// copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into dst.
30static void copy_v(void* dst) {}
mtkleinec559592016-08-06 20:31:30 -070031
mtklein03591a72016-08-07 13:35:46 -070032template <typename S, typename... Rest>
33static void copy_v(void* dst, const S* src, int n, Rest&&... rest) {
34 SkASSERTF(((uintptr_t)dst & (alignof(S)-1)) == 0,
35 "Expected %p to be aligned for at least %zu bytes.", dst, alignof(S));
36 sk_careful_memcpy(dst, src, n*sizeof(S));
37 copy_v(SkTAddOffset<void>(dst, n*sizeof(S)), std::forward<Rest>(rest)...);
mtkleinec559592016-08-06 20:31:30 -070038}
39
mtklein03591a72016-08-07 13:35:46 -070040// Helper for getting back at arrays which have been copy_v'd together after an Op.
mtklein29de8d92016-08-07 11:35:08 -070041template <typename D, typename T>
42static D* pod(T* op, size_t offset = 0) {
43 return SkTAddOffset<D>(op+1, offset);
44}
45
mtklein03591a72016-08-07 13:35:46 -070046// Pre-cache lazy non-threadsafe fields on SkPath and/or SkMatrix.
47static void make_threadsafe(SkPath* path, SkMatrix* matrix) {
48 if (path) { path->updateBoundsCache(); }
49 if (matrix) { (void)matrix->getType(); }
50}
51
mtklein9c5052f2016-08-06 12:51:51 -070052namespace {
mtkleind559eb22016-08-11 07:08:28 -070053#define TYPES(M) \
54 M(Save) M(Restore) M(SaveLayer) \
mtkleincbdf0072016-08-19 09:05:27 -070055 M(Concat) M(SetMatrix) M(Translate) M(TranslateZ) \
mtkleind559eb22016-08-11 07:08:28 -070056 M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \
57 M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawOval) M(DrawRRect) M(DrawDRRect) \
58 M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) M(DrawShadowedPicture) \
59 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
mtkleind559eb22016-08-11 07:08:28 -070076 struct Save final : Op {
77 static const auto kType = Type::Save;
mtklein64806192016-08-16 17:18:27 -070078 void draw(SkCanvas* c, const SkMatrix&) { c->save(); }
mtkleind559eb22016-08-11 07:08:28 -070079 };
80 struct Restore final : Op {
81 static const auto kType = Type::Restore;
mtklein64806192016-08-16 17:18:27 -070082 void draw(SkCanvas* c, const SkMatrix&) { c->restore(); }
mtkleind559eb22016-08-11 07:08:28 -070083 };
mtklein6f8411d2016-08-06 15:28:11 -070084 struct SaveLayer final : Op {
mtkleind559eb22016-08-11 07:08:28 -070085 static const auto kType = Type::SaveLayer;
mtklein6f8411d2016-08-06 15:28:11 -070086 SaveLayer(const SkRect* bounds, const SkPaint* paint,
mtklein29de8d92016-08-07 11:35:08 -070087 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
mtklein6f8411d2016-08-06 15:28:11 -070088 if (bounds) { this->bounds = *bounds; }
89 if (paint) { this->paint = *paint; }
90 this->backdrop = sk_ref_sp(backdrop);
91 this->flags = flags;
92 }
mtklein29de8d92016-08-07 11:35:08 -070093 SkRect bounds = kUnset;
mtklein6f8411d2016-08-06 15:28:11 -070094 SkPaint paint;
95 sk_sp<const SkImageFilter> backdrop;
mtklein29de8d92016-08-07 11:35:08 -070096 SkCanvas::SaveLayerFlags flags;
mtklein64806192016-08-16 17:18:27 -070097 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -070098 c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags });
mtklein6f8411d2016-08-06 15:28:11 -070099 }
100 };
mtklein9c5052f2016-08-06 12:51:51 -0700101
102 struct Concat final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700103 static const auto kType = Type::Concat;
mtklein9c5052f2016-08-06 12:51:51 -0700104 Concat(const SkMatrix& matrix) : matrix(matrix) {}
105 SkMatrix matrix;
mtklein64806192016-08-16 17:18:27 -0700106 void draw(SkCanvas* c, const SkMatrix&) { c->concat(matrix); }
mtkleind559eb22016-08-11 07:08:28 -0700107 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein9c5052f2016-08-06 12:51:51 -0700108 };
109 struct SetMatrix final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700110 static const auto kType = Type::SetMatrix;
mtklein9c5052f2016-08-06 12:51:51 -0700111 SetMatrix(const SkMatrix& matrix) : matrix(matrix) {}
112 SkMatrix matrix;
mtklein64806192016-08-16 17:18:27 -0700113 void draw(SkCanvas* c, const SkMatrix& original) {
114 c->setMatrix(SkMatrix::Concat(original, matrix));
115 }
mtkleind559eb22016-08-11 07:08:28 -0700116 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein9c5052f2016-08-06 12:51:51 -0700117 };
mtkleincbdf0072016-08-19 09:05:27 -0700118 struct Translate final : Op {
119 static const auto kType = Type::Translate;
120 Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
121 SkScalar dx,dy;
122 void draw(SkCanvas* c, const SkMatrix&) {
123 c->translate(dx, dy);
124 }
125 };
mtklein29de8d92016-08-07 11:35:08 -0700126 struct TranslateZ final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700127 static const auto kType = Type::TranslateZ;
mtklein29de8d92016-08-07 11:35:08 -0700128 TranslateZ(SkScalar dz) : dz(dz) {}
129 SkScalar dz;
mtklein64806192016-08-16 17:18:27 -0700130 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700131 #ifdef SK_EXPERIMENTAL_SHADOWING
132 c->translateZ(dz);
133 #endif
134 }
135 };
mtklein9c5052f2016-08-06 12:51:51 -0700136
mtklein6f8411d2016-08-06 15:28:11 -0700137 struct ClipPath final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700138 static const auto kType = Type::ClipPath;
mtklein6f8411d2016-08-06 15:28:11 -0700139 ClipPath(const SkPath& path, SkRegion::Op op, bool aa) : path(path), op(op), aa(aa) {}
140 SkPath path;
141 SkRegion::Op op;
142 bool aa;
mtklein64806192016-08-16 17:18:27 -0700143 void draw(SkCanvas* c, const SkMatrix&) { c->clipPath(path, op, aa); }
mtkleind559eb22016-08-11 07:08:28 -0700144 void makeThreadsafe() { make_threadsafe(&path, nullptr); }
mtklein6f8411d2016-08-06 15:28:11 -0700145 };
mtklein9c5052f2016-08-06 12:51:51 -0700146 struct ClipRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700147 static const auto kType = Type::ClipRect;
mtklein9c5052f2016-08-06 12:51:51 -0700148 ClipRect(const SkRect& rect, SkRegion::Op op, bool aa) : rect(rect), op(op), aa(aa) {}
149 SkRect rect;
150 SkRegion::Op op;
151 bool aa;
mtklein64806192016-08-16 17:18:27 -0700152 void draw(SkCanvas* c, const SkMatrix&) { c->clipRect(rect, op, aa); }
mtklein9c5052f2016-08-06 12:51:51 -0700153 };
mtklein6f8411d2016-08-06 15:28:11 -0700154 struct ClipRRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700155 static const auto kType = Type::ClipRRect;
mtklein6f8411d2016-08-06 15:28:11 -0700156 ClipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) : rrect(rrect), op(op), aa(aa) {}
157 SkRRect rrect;
158 SkRegion::Op op;
159 bool aa;
mtklein64806192016-08-16 17:18:27 -0700160 void draw(SkCanvas* c, const SkMatrix&) { c->clipRRect(rrect, op, aa); }
mtklein6f8411d2016-08-06 15:28:11 -0700161 };
162 struct ClipRegion final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700163 static const auto kType = Type::ClipRegion;
mtklein6f8411d2016-08-06 15:28:11 -0700164 ClipRegion(const SkRegion& region, SkRegion::Op op) : region(region), op(op) {}
165 SkRegion region;
166 SkRegion::Op op;
mtklein64806192016-08-16 17:18:27 -0700167 void draw(SkCanvas* c, const SkMatrix&) { c->clipRegion(region, op); }
mtklein6f8411d2016-08-06 15:28:11 -0700168 };
mtklein9c5052f2016-08-06 12:51:51 -0700169
mtklein6f8411d2016-08-06 15:28:11 -0700170 struct DrawPaint final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700171 static const auto kType = Type::DrawPaint;
mtklein6f8411d2016-08-06 15:28:11 -0700172 DrawPaint(const SkPaint& paint) : paint(paint) {}
173 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700174 void draw(SkCanvas* c, const SkMatrix&) { c->drawPaint(paint); }
mtklein6f8411d2016-08-06 15:28:11 -0700175 };
176 struct DrawPath final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700177 static const auto kType = Type::DrawPath;
mtklein6f8411d2016-08-06 15:28:11 -0700178 DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
179 SkPath path;
180 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700181 void draw(SkCanvas* c, const SkMatrix&) { c->drawPath(path, paint); }
mtkleind559eb22016-08-11 07:08:28 -0700182 void makeThreadsafe() { make_threadsafe(&path, nullptr); }
mtklein6f8411d2016-08-06 15:28:11 -0700183 };
mtklein9c5052f2016-08-06 12:51:51 -0700184 struct DrawRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700185 static const auto kType = Type::DrawRect;
mtklein9c5052f2016-08-06 12:51:51 -0700186 DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {}
187 SkRect rect;
188 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700189 void draw(SkCanvas* c, const SkMatrix&) { c->drawRect(rect, paint); }
mtklein9c5052f2016-08-06 12:51:51 -0700190 };
mtklein6f8411d2016-08-06 15:28:11 -0700191 struct DrawOval final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700192 static const auto kType = Type::DrawOval;
mtklein6f8411d2016-08-06 15:28:11 -0700193 DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {}
194 SkRect oval;
mtklein9c5052f2016-08-06 12:51:51 -0700195 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700196 void draw(SkCanvas* c, const SkMatrix&) { c->drawOval(oval, paint); }
mtklein6f8411d2016-08-06 15:28:11 -0700197 };
198 struct DrawRRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700199 static const auto kType = Type::DrawRRect;
mtklein6f8411d2016-08-06 15:28:11 -0700200 DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {}
201 SkRRect rrect;
202 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700203 void draw(SkCanvas* c, const SkMatrix&) { c->drawRRect(rrect, paint); }
mtklein6f8411d2016-08-06 15:28:11 -0700204 };
205 struct DrawDRRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700206 static const auto kType = Type::DrawDRRect;
mtklein6f8411d2016-08-06 15:28:11 -0700207 DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
208 : outer(outer), inner(inner), paint(paint) {}
209 SkRRect outer, inner;
210 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700211 void draw(SkCanvas* c, const SkMatrix&) { c->drawDRRect(outer, inner, paint); }
mtklein9c5052f2016-08-06 12:51:51 -0700212 };
213
mtklein29de8d92016-08-07 11:35:08 -0700214 struct DrawAnnotation final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700215 static const auto kType = Type::DrawAnnotation;
mtklein29de8d92016-08-07 11:35:08 -0700216 DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {}
217 SkRect rect;
218 sk_sp<SkData> value;
mtklein64806192016-08-16 17:18:27 -0700219 void draw(SkCanvas* c, const SkMatrix&) {
220 c->drawAnnotation(rect, pod<char>(this), value.get());
221 }
mtklein29de8d92016-08-07 11:35:08 -0700222 };
223 struct DrawDrawable final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700224 static const auto kType = Type::DrawDrawable;
mtklein29de8d92016-08-07 11:35:08 -0700225 DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) {
226 if (matrix) { this->matrix = *matrix; }
227 }
mtklein03591a72016-08-07 13:35:46 -0700228 sk_sp<SkDrawable> drawable;
229 sk_sp<const SkPicture> snapped;
230 SkMatrix matrix = SkMatrix::I();
mtklein64806192016-08-16 17:18:27 -0700231 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700232 snapped ? c->drawPicture(snapped.get(), &matrix, nullptr)
233 : c->drawDrawable(drawable.get(), &matrix);
234 }
mtkleind559eb22016-08-11 07:08:28 -0700235 void makeThreadsafe() {
mtklein03591a72016-08-07 13:35:46 -0700236 snapped.reset(drawable->newPictureSnapshot());
237 make_threadsafe(nullptr, &matrix);
238 }
mtklein29de8d92016-08-07 11:35:08 -0700239 };
240 struct DrawPicture final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700241 static const auto kType = Type::DrawPicture;
mtklein29de8d92016-08-07 11:35:08 -0700242 DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
243 : picture(sk_ref_sp(picture)) {
244 if (matrix) { this->matrix = *matrix; }
mtklein03591a72016-08-07 13:35:46 -0700245 if (paint) { this->paint = *paint; has_paint = true; }
mtklein29de8d92016-08-07 11:35:08 -0700246 }
247 sk_sp<const SkPicture> picture;
248 SkMatrix matrix = SkMatrix::I();
249 SkPaint paint;
mtklein03591a72016-08-07 13:35:46 -0700250 bool has_paint = false; // TODO: why is a default paint not the same?
mtklein64806192016-08-16 17:18:27 -0700251 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700252 c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr);
253 }
mtkleind559eb22016-08-11 07:08:28 -0700254 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein29de8d92016-08-07 11:35:08 -0700255 };
256 struct DrawShadowedPicture final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700257 static const auto kType = Type::DrawShadowedPicture;
mtklein29de8d92016-08-07 11:35:08 -0700258 DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
259 : picture(sk_ref_sp(picture)) {
260 if (matrix) { this->matrix = *matrix; }
261 if (paint) { this->paint = *paint; }
262 }
263 sk_sp<const SkPicture> picture;
264 SkMatrix matrix = SkMatrix::I();
265 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700266 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700267 #ifdef SK_EXPERIMENTAL_SHADOWING
268 c->drawShadowedPicture(picture.get(), &matrix, &paint);
269 #endif
270 }
mtkleind559eb22016-08-11 07:08:28 -0700271 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
mtklein29de8d92016-08-07 11:35:08 -0700272 };
273
mtkleinec559592016-08-06 20:31:30 -0700274 struct DrawImage final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700275 static const auto kType = Type::DrawImage;
mtkleinec559592016-08-06 20:31:30 -0700276 DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700277 : image(std::move(image)), x(x), y(y) {
mtkleinec559592016-08-06 20:31:30 -0700278 if (paint) { this->paint = *paint; }
mtklein9c5052f2016-08-06 12:51:51 -0700279 }
mtkleinec559592016-08-06 20:31:30 -0700280 sk_sp<const SkImage> image;
281 SkScalar x,y;
282 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700283 void draw(SkCanvas* c, const SkMatrix&) { c->drawImage(image.get(), x,y, &paint); }
mtkleinec559592016-08-06 20:31:30 -0700284 };
285 struct DrawImageNine final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700286 static const auto kType = Type::DrawImageNine;
mtkleinec559592016-08-06 20:31:30 -0700287 DrawImageNine(sk_sp<const SkImage>&& image,
288 const SkIRect& center, const SkRect& dst, const SkPaint* paint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700289 : image(std::move(image)), center(center), dst(dst) {
mtkleinec559592016-08-06 20:31:30 -0700290 if (paint) { this->paint = *paint; }
291 }
292 sk_sp<const SkImage> image;
293 SkIRect center;
294 SkRect dst;
295 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700296 void draw(SkCanvas* c, const SkMatrix&) {
297 c->drawImageNine(image.get(), center, dst, &paint);
298 }
mtkleinec559592016-08-06 20:31:30 -0700299 };
300 struct DrawImageRect final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700301 static const auto kType = Type::DrawImageRect;
mtkleinec559592016-08-06 20:31:30 -0700302 DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
303 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700304 : image(std::move(image)), dst(dst), constraint(constraint) {
mtkleinec559592016-08-06 20:31:30 -0700305 this->src = src ? *src : SkRect::MakeIWH(image->width(), image->height());
306 if (paint) { this->paint = *paint; }
307 }
308 sk_sp<const SkImage> image;
309 SkRect src, dst;
310 SkPaint paint;
311 SkCanvas::SrcRectConstraint constraint;
mtklein64806192016-08-16 17:18:27 -0700312 void draw(SkCanvas* c, const SkMatrix&) {
mtkleinec559592016-08-06 20:31:30 -0700313 c->drawImageRect(image.get(), src, dst, &paint, constraint);
314 }
mtkleinec559592016-08-06 20:31:30 -0700315 };
mtklein29de8d92016-08-07 11:35:08 -0700316 struct DrawImageLattice final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700317 static const auto kType = Type::DrawImageLattice;
mtklein29de8d92016-08-07 11:35:08 -0700318 DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys,
319 const SkRect& dst, const SkPaint* paint)
mtkleinbaeec6d2016-08-09 15:09:39 -0700320 : image(std::move(image)), xs(xs), ys(ys), dst(dst) {
mtklein29de8d92016-08-07 11:35:08 -0700321 if (paint) { this->paint = *paint; }
322 }
323 sk_sp<const SkImage> image;
324 int xs, ys;
325 SkRect dst;
326 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700327 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700328 auto xdivs = pod<int>(this, 0),
329 ydivs = pod<int>(this, xs*sizeof(int));
330 c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint);
331 }
mtklein29de8d92016-08-07 11:35:08 -0700332 };
mtkleinec559592016-08-06 20:31:30 -0700333
334 struct DrawText final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700335 static const auto kType = Type::DrawText;
mtkleinec559592016-08-06 20:31:30 -0700336 DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint)
337 : bytes(bytes), x(x), y(y), paint(paint) {}
338 size_t bytes;
339 SkScalar x,y;
340 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700341 void draw(SkCanvas* c, const SkMatrix&) {
342 c->drawText(pod<void>(this), bytes, x,y, paint);
343 }
mtkleinec559592016-08-06 20:31:30 -0700344 };
345 struct DrawPosText final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700346 static const auto kType = Type::DrawPosText;
mtklein03591a72016-08-07 13:35:46 -0700347 DrawPosText(size_t bytes, const SkPaint& paint, int n)
348 : bytes(bytes), paint(paint), n(n) {}
mtkleinec559592016-08-06 20:31:30 -0700349 size_t bytes;
350 SkPaint paint;
mtklein03591a72016-08-07 13:35:46 -0700351 int n;
mtklein64806192016-08-16 17:18:27 -0700352 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700353 auto points = pod<SkPoint>(this);
354 auto text = pod<void>(this, n*sizeof(SkPoint));
355 c->drawPosText(text, bytes, points, paint);
mtkleinec559592016-08-06 20:31:30 -0700356 }
mtkleinec559592016-08-06 20:31:30 -0700357 };
358 struct DrawPosTextH final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700359 static const auto kType = Type::DrawPosTextH;
mtklein03591a72016-08-07 13:35:46 -0700360 DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n)
361 : bytes(bytes), y(y), paint(paint), n(n) {}
mtklein29de8d92016-08-07 11:35:08 -0700362 size_t bytes;
mtkleinec559592016-08-06 20:31:30 -0700363 SkScalar y;
mtklein29de8d92016-08-07 11:35:08 -0700364 SkPaint paint;
mtklein03591a72016-08-07 13:35:46 -0700365 int n;
mtklein64806192016-08-16 17:18:27 -0700366 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700367 auto xs = pod<SkScalar>(this);
368 auto text = pod<void>(this, n*sizeof(SkScalar));
369 c->drawPosTextH(text, bytes, xs, y, paint);
mtklein29de8d92016-08-07 11:35:08 -0700370 }
mtklein29de8d92016-08-07 11:35:08 -0700371 };
372 struct DrawTextOnPath final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700373 static const auto kType = Type::DrawTextOnPath;
mtklein29de8d92016-08-07 11:35:08 -0700374 DrawTextOnPath(size_t bytes, const SkPath& path,
375 const SkMatrix* matrix, const SkPaint& paint)
376 : bytes(bytes), path(path), paint(paint) {
377 if (matrix) { this->matrix = *matrix; }
378 }
379 size_t bytes;
380 SkPath path;
381 SkMatrix matrix = SkMatrix::I();
382 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700383 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700384 c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint);
385 }
mtkleind559eb22016-08-11 07:08:28 -0700386 void makeThreadsafe() { make_threadsafe(&path, &matrix); }
mtklein29de8d92016-08-07 11:35:08 -0700387 };
388 struct DrawTextRSXform final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700389 static const auto kType = Type::DrawTextRSXform;
mtklein29de8d92016-08-07 11:35:08 -0700390 DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint)
391 : bytes(bytes), paint(paint) {
392 if (cull) { this->cull = *cull; }
393 }
394 size_t bytes;
395 SkRect cull = kUnset;
mtkleinec559592016-08-06 20:31:30 -0700396 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700397 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700398 c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes),
399 maybe_unset(cull), paint);
mtkleinec559592016-08-06 20:31:30 -0700400 }
mtkleinec559592016-08-06 20:31:30 -0700401 };
402 struct DrawTextBlob final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700403 static const auto kType = Type::DrawTextBlob;
mtkleinec559592016-08-06 20:31:30 -0700404 DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
405 : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
406 sk_sp<const SkTextBlob> blob;
407 SkScalar x,y;
408 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700409 void draw(SkCanvas* c, const SkMatrix&) {
410 c->drawTextBlob(blob.get(), x,y, paint);
411 }
mtkleinec559592016-08-06 20:31:30 -0700412 };
mtklein29de8d92016-08-07 11:35:08 -0700413
mtklein03591a72016-08-07 13:35:46 -0700414 struct DrawPatch final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700415 static const auto kType = Type::DrawPatch;
mtklein03591a72016-08-07 13:35:46 -0700416 DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
417 SkXfermode* xfermode, const SkPaint& paint)
418 : xfermode(sk_ref_sp(xfermode)), paint(paint) {
419 copy_v(this->cubics, cubics, 12);
420 if (colors) { copy_v(this->colors, colors, 4); has_colors = true; }
421 if (texs ) { copy_v(this->texs , texs , 4); has_texs = true; }
422 }
423 SkPoint cubics[12];
424 SkColor colors[4];
425 SkPoint texs[4];
426 sk_sp<SkXfermode> xfermode;
427 SkPaint paint;
428 bool has_colors = false;
429 bool has_texs = false;
mtklein64806192016-08-16 17:18:27 -0700430 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700431 c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr,
432 xfermode.get(), paint);
433 }
mtklein03591a72016-08-07 13:35:46 -0700434 };
mtklein29de8d92016-08-07 11:35:08 -0700435 struct DrawPoints final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700436 static const auto kType = Type::DrawPoints;
mtklein29de8d92016-08-07 11:35:08 -0700437 DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint)
438 : mode(mode), count(count), paint(paint) {}
439 SkCanvas::PointMode mode;
440 size_t count;
441 SkPaint paint;
mtklein64806192016-08-16 17:18:27 -0700442 void draw(SkCanvas* c, const SkMatrix&) {
443 c->drawPoints(mode, count, pod<SkPoint>(this), paint);
444 }
mtklein29de8d92016-08-07 11:35:08 -0700445 };
mtklein03591a72016-08-07 13:35:46 -0700446 struct DrawVertices final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700447 static const auto kType = Type::DrawVertices;
mtklein03591a72016-08-07 13:35:46 -0700448 DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices,
449 const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices)
450 : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices)
451 , paint(paint), has_texs(has_texs), has_colors(has_colors), has_indices(has_indices) {}
452 SkCanvas::VertexMode mode;
453 int count;
454 sk_sp<SkXfermode> xfermode;
455 int nindices;
456 SkPaint paint;
457 bool has_texs;
458 bool has_colors;
459 bool has_indices;
mtklein64806192016-08-16 17:18:27 -0700460 void draw(SkCanvas* c, const SkMatrix&) {
mtklein03591a72016-08-07 13:35:46 -0700461 SkPoint* vertices = pod<SkPoint>(this, 0);
462 size_t offset = count*sizeof(SkPoint);
463
464 SkPoint* texs = nullptr;
465 if (has_texs) {
466 texs = pod<SkPoint>(this, offset);
467 offset += count*sizeof(SkPoint);
468 }
469
470 SkColor* colors = nullptr;
471 if (has_colors) {
472 colors = pod<SkColor>(this, offset);
473 offset += count*sizeof(SkColor);
474 }
475
476 uint16_t* indices = nullptr;
477 if (has_indices) {
478 indices = pod<uint16_t>(this, offset);
479 }
480 c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(),
481 indices, nindices, paint);
482 }
mtklein03591a72016-08-07 13:35:46 -0700483 };
mtklein29de8d92016-08-07 11:35:08 -0700484 struct DrawAtlas final : Op {
mtkleind559eb22016-08-11 07:08:28 -0700485 static const auto kType = Type::DrawAtlas;
mtklein29de8d92016-08-07 11:35:08 -0700486 DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode,
487 const SkRect* cull, const SkPaint* paint, bool has_colors)
488 : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) {
489 if (cull) { this->cull = *cull; }
490 if (paint) { this->paint = *paint; }
491 }
492 sk_sp<const SkImage> atlas;
493 int count;
494 SkXfermode::Mode xfermode;
495 SkRect cull = kUnset;
496 SkPaint paint;
497 bool has_colors;
mtklein64806192016-08-16 17:18:27 -0700498 void draw(SkCanvas* c, const SkMatrix&) {
mtklein29de8d92016-08-07 11:35:08 -0700499 auto xforms = pod<SkRSXform>(this, 0);
500 auto texs = pod<SkRect>(this, count*sizeof(SkRSXform));
501 auto colors = has_colors
502 ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect)))
503 : nullptr;
504 c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode,
505 maybe_unset(cull), &paint);
506 }
mtklein29de8d92016-08-07 11:35:08 -0700507 };
mtkleinec559592016-08-06 20:31:30 -0700508}
509
510template <typename T, typename... Args>
mtkleinb2028332016-08-09 15:13:18 -0700511void* SkLiteDL::push(size_t pod, Args&&... args) {
mtkleinec559592016-08-06 20:31:30 -0700512 size_t skip = SkAlignPtr(sizeof(T) + pod);
mtkleind559eb22016-08-11 07:08:28 -0700513 SkASSERT(skip < (1<<24));
mtkleinb2028332016-08-09 15:13:18 -0700514 if (fUsed + skip > fReserved) {
mtklein883c8ef2016-08-16 09:36:18 -0700515 static_assert(SkIsPow2(SKLITEDL_PAGE), "This math needs updating for non-pow2.");
516 // Next greater multiple of SKLITEDL_PAGE.
517 fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE-1);
mtkleinb2028332016-08-09 15:13:18 -0700518 fBytes.realloc(fReserved);
519 }
520 SkASSERT(fUsed + skip <= fReserved);
521 auto op = (T*)(fBytes.get() + fUsed);
522 fUsed += skip;
mtkleinec559592016-08-06 20:31:30 -0700523 new (op) T{ std::forward<Args>(args)... };
mtkleind559eb22016-08-11 07:08:28 -0700524 op->type = (uint32_t)T::kType;
mtkleinec559592016-08-06 20:31:30 -0700525 op->skip = skip;
526 return op+1;
527}
528
mtklein64806192016-08-16 17:18:27 -0700529template <typename Fn, typename... Args>
530inline void SkLiteDL::map(const Fn fns[], Args... args) {
mtkleinb2028332016-08-09 15:13:18 -0700531 auto end = fBytes.get() + fUsed;
532 for (uint8_t* ptr = fBytes.get(); ptr < end; ) {
mtkleinec559592016-08-06 20:31:30 -0700533 auto op = (Op*)ptr;
mtkleind559eb22016-08-11 07:08:28 -0700534 auto type = op->type;
535 auto skip = op->skip;
536 if (auto fn = fns[type]) { // We replace no-op functions with nullptrs
537 fn(op, args...); // to avoid the overhead of a pointless call.
538 }
539 ptr += skip;
mtklein9c5052f2016-08-06 12:51:51 -0700540 }
541}
542
mtkleinb2028332016-08-09 15:13:18 -0700543void SkLiteDL:: save() { this->push <Save>(0); }
544void SkLiteDL::restore() { this->push<Restore>(0); }
mtklein6f8411d2016-08-06 15:28:11 -0700545void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint,
mtklein29de8d92016-08-07 11:35:08 -0700546 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
mtkleinb2028332016-08-09 15:13:18 -0700547 this->push<SaveLayer>(0, bounds, paint, backdrop, flags);
mtklein6f8411d2016-08-06 15:28:11 -0700548}
mtklein9c5052f2016-08-06 12:51:51 -0700549
mtkleincbdf0072016-08-19 09:05:27 -0700550void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); }
551void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); }
552void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); }
mtkleinb2028332016-08-09 15:13:18 -0700553void SkLiteDL::translateZ(SkScalar dz) { this->push<TranslateZ>(0, dz); }
mtklein9c5052f2016-08-06 12:51:51 -0700554
mtklein6f8411d2016-08-06 15:28:11 -0700555void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) {
mtkleinb2028332016-08-09 15:13:18 -0700556 this->push<ClipPath>(0, path, op, aa);
mtklein6f8411d2016-08-06 15:28:11 -0700557}
mtklein9c5052f2016-08-06 12:51:51 -0700558void SkLiteDL::clipRect(const SkRect& rect, SkRegion::Op op, bool aa) {
mtkleinb2028332016-08-09 15:13:18 -0700559 this->push<ClipRect>(0, rect, op, aa);
mtklein9c5052f2016-08-06 12:51:51 -0700560}
mtklein6f8411d2016-08-06 15:28:11 -0700561void SkLiteDL::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) {
mtkleinb2028332016-08-09 15:13:18 -0700562 this->push<ClipRRect>(0, rrect, op, aa);
mtklein6f8411d2016-08-06 15:28:11 -0700563}
564void SkLiteDL::clipRegion(const SkRegion& region, SkRegion::Op op) {
mtkleinb2028332016-08-09 15:13:18 -0700565 this->push<ClipRegion>(0, region, op);
mtklein6f8411d2016-08-06 15:28:11 -0700566}
mtklein9c5052f2016-08-06 12:51:51 -0700567
mtklein6f8411d2016-08-06 15:28:11 -0700568void SkLiteDL::drawPaint(const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700569 this->push<DrawPaint>(0, paint);
mtklein9c5052f2016-08-06 12:51:51 -0700570}
571void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700572 this->push<DrawPath>(0, path, paint);
mtklein9c5052f2016-08-06 12:51:51 -0700573}
mtklein6f8411d2016-08-06 15:28:11 -0700574void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700575 this->push<DrawRect>(0, rect, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700576}
577void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700578 this->push<DrawOval>(0, oval, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700579}
580void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700581 this->push<DrawRRect>(0, rrect, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700582}
583void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700584 this->push<DrawDRRect>(0, outer, inner, paint);
mtklein6f8411d2016-08-06 15:28:11 -0700585}
mtklein9c5052f2016-08-06 12:51:51 -0700586
mtklein29de8d92016-08-07 11:35:08 -0700587void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) {
588 size_t bytes = strlen(key)+1;
mtkleinb2028332016-08-09 15:13:18 -0700589 void* pod = this->push<DrawAnnotation>(bytes, rect, value);
mtklein03591a72016-08-07 13:35:46 -0700590 copy_v(pod, key,bytes);
mtklein29de8d92016-08-07 11:35:08 -0700591}
592void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
mtkleinb2028332016-08-09 15:13:18 -0700593 this->push<DrawDrawable>(0, drawable, matrix);
mtklein29de8d92016-08-07 11:35:08 -0700594}
595void SkLiteDL::drawPicture(const SkPicture* picture,
596 const SkMatrix* matrix, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700597 this->push<DrawPicture>(0, picture, matrix, paint);
mtklein29de8d92016-08-07 11:35:08 -0700598}
599void SkLiteDL::drawShadowedPicture(const SkPicture* picture,
600 const SkMatrix* matrix, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700601 this->push<DrawShadowedPicture>(0, picture, matrix, paint);
mtklein29de8d92016-08-07 11:35:08 -0700602}
603
mtkleinec559592016-08-06 20:31:30 -0700604void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700605 this->push<DrawImage>(0, SkImage::MakeFromBitmap(bm), x,y, paint);
mtkleinec559592016-08-06 20:31:30 -0700606}
607void SkLiteDL::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
608 const SkRect& dst, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700609 this->push<DrawImageNine>(0, SkImage::MakeFromBitmap(bm), center, dst, paint);
mtkleinec559592016-08-06 20:31:30 -0700610}
611void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
612 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
mtkleinb2028332016-08-09 15:13:18 -0700613 this->push<DrawImageRect>(0, SkImage::MakeFromBitmap(bm), src, dst, paint, constraint);
mtkleinec559592016-08-06 20:31:30 -0700614}
msarett16882062016-08-16 09:31:08 -0700615void SkLiteDL::drawBitmapLattice(const SkBitmap& bm, const SkCanvas::Lattice& lattice,
616 const SkRect& dst, const SkPaint* paint) {
617 int xs = lattice.fXCount, ys = lattice.fYCount;
618 size_t bytes = (xs + ys) * sizeof(int);
619 void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, dst,
620 paint);
621 copy_v(pod, lattice.fXDivs, xs,
622 lattice.fYDivs, ys);
623}
mtkleinec559592016-08-06 20:31:30 -0700624
625void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700626 this->push<DrawImage>(0, sk_ref_sp(image), x,y, paint);
mtkleinec559592016-08-06 20:31:30 -0700627}
628void SkLiteDL::drawImageNine(const SkImage* image, const SkIRect& center,
629 const SkRect& dst, const SkPaint* paint) {
mtkleinb2028332016-08-09 15:13:18 -0700630 this->push<DrawImageNine>(0, sk_ref_sp(image), center, dst, paint);
mtkleinec559592016-08-06 20:31:30 -0700631}
632void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
633 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
mtkleinb2028332016-08-09 15:13:18 -0700634 this->push<DrawImageRect>(0, sk_ref_sp(image), src, dst, paint, constraint);
mtkleinec559592016-08-06 20:31:30 -0700635}
mtklein29de8d92016-08-07 11:35:08 -0700636void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
637 const SkRect& dst, const SkPaint* paint) {
638 int xs = lattice.fXCount, ys = lattice.fYCount;
639 size_t bytes = (xs + ys) * sizeof(int);
mtkleinb2028332016-08-09 15:13:18 -0700640 void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, dst, paint);
mtklein03591a72016-08-07 13:35:46 -0700641 copy_v(pod, lattice.fXDivs, xs,
642 lattice.fYDivs, ys);
mtklein29de8d92016-08-07 11:35:08 -0700643}
mtkleinec559592016-08-06 20:31:30 -0700644
645void SkLiteDL::drawText(const void* text, size_t bytes,
646 SkScalar x, SkScalar y, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700647 void* pod = this->push<DrawText>(bytes, bytes, x, y, paint);
mtklein03591a72016-08-07 13:35:46 -0700648 copy_v(pod, (const char*)text,bytes);
mtkleinec559592016-08-06 20:31:30 -0700649}
650void SkLiteDL::drawPosText(const void* text, size_t bytes,
651 const SkPoint pos[], const SkPaint& paint) {
652 int n = paint.countText(text, bytes);
mtkleinb2028332016-08-09 15:13:18 -0700653 void* pod = this->push<DrawPosText>(n*sizeof(SkPoint)+bytes, bytes, paint, n);
mtklein03591a72016-08-07 13:35:46 -0700654 copy_v(pod, pos,n, (const char*)text,bytes);
mtkleinec559592016-08-06 20:31:30 -0700655}
656void SkLiteDL::drawPosTextH(const void* text, size_t bytes,
657 const SkScalar xs[], SkScalar y, const SkPaint& paint) {
658 int n = paint.countText(text, bytes);
mtkleinb2028332016-08-09 15:13:18 -0700659 void* pod = this->push<DrawPosTextH>(n*sizeof(SkScalar)+bytes, bytes, y, paint, n);
mtklein03591a72016-08-07 13:35:46 -0700660 copy_v(pod, xs,n, (const char*)text,bytes);
mtkleinec559592016-08-06 20:31:30 -0700661}
mtklein29de8d92016-08-07 11:35:08 -0700662void SkLiteDL::drawTextOnPath(const void* text, size_t bytes,
663 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700664 void* pod = this->push<DrawTextOnPath>(bytes, bytes, path, matrix, paint);
mtklein03591a72016-08-07 13:35:46 -0700665 copy_v(pod, (const char*)text,bytes);
mtklein29de8d92016-08-07 11:35:08 -0700666}
667void SkLiteDL::drawTextRSXform(const void* text, size_t bytes,
668 const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) {
669 int n = paint.countText(text, bytes);
mtkleinb2028332016-08-09 15:13:18 -0700670 void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, cull, paint);
mtklein03591a72016-08-07 13:35:46 -0700671 copy_v(pod, (const char*)text,bytes, xforms,n);
mtklein29de8d92016-08-07 11:35:08 -0700672}
mtkleinec559592016-08-06 20:31:30 -0700673void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700674 this->push<DrawTextBlob>(0, blob, x,y, paint);
mtkleinec559592016-08-06 20:31:30 -0700675}
676
mtklein03591a72016-08-07 13:35:46 -0700677void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4],
678 SkXfermode* xfermode, const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700679 this->push<DrawPatch>(0, points, colors, texs, xfermode, paint);
mtklein03591a72016-08-07 13:35:46 -0700680}
mtklein29de8d92016-08-07 11:35:08 -0700681void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[],
682 const SkPaint& paint) {
mtkleinb2028332016-08-09 15:13:18 -0700683 void* pod = this->push<DrawPoints>(count*sizeof(SkPoint), mode, count, paint);
mtklein03591a72016-08-07 13:35:46 -0700684 copy_v(pod, points,count);
685}
686void SkLiteDL::drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[],
687 const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode,
688 const uint16_t indices[], int nindices, const SkPaint& paint) {
689 size_t bytes = count * sizeof(SkPoint);
690 if (texs ) { bytes += count * sizeof(SkPoint); }
691 if (colors) { bytes += count * sizeof(SkColor); }
692 if (indices) { bytes += nindices * sizeof(uint16_t); }
mtkleinb2028332016-08-09 15:13:18 -0700693 void* pod = this->push<DrawVertices>(bytes, mode, count, xfermode, nindices, paint,
694 texs != nullptr, colors != nullptr, indices != nullptr);
mtklein03591a72016-08-07 13:35:46 -0700695 copy_v(pod, vertices, count,
696 texs, texs ? count : 0,
697 colors, colors ? count : 0,
698 indices, indices ? nindices : 0);
mtklein29de8d92016-08-07 11:35:08 -0700699}
700void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
701 const SkColor colors[], int count, SkXfermode::Mode xfermode,
702 const SkRect* cull, const SkPaint* paint) {
703 size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect));
704 if (colors) {
705 bytes += count*sizeof(SkColor);
706 }
mtkleinb2028332016-08-09 15:13:18 -0700707 void* pod = this->push<DrawAtlas>(bytes,
708 atlas, count, xfermode, cull, paint, colors != nullptr);
mtklein03591a72016-08-07 13:35:46 -0700709 copy_v(pod, xforms, count,
710 texs, count,
711 colors, colors ? count : 0);
mtklein29de8d92016-08-07 11:35:08 -0700712}
713
mtklein91cd2802016-08-17 11:39:48 -0700714typedef void(*draw_fn)(void*, SkCanvas*, const SkMatrix&);
715typedef void(*void_fn)(void*);
mtkleinec559592016-08-06 20:31:30 -0700716
mtkleind559eb22016-08-11 07:08:28 -0700717// All ops implement draw().
mtklein64806192016-08-16 17:18:27 -0700718#define M(T) [](void* op, SkCanvas* c, const SkMatrix& original) { ((T*)op)->draw(c, original); },
719static const draw_fn draw_fns[] = { TYPES(M) };
mtkleind559eb22016-08-11 07:08:28 -0700720#undef M
mtklein9c5052f2016-08-06 12:51:51 -0700721
mtklein91cd2802016-08-17 11:39:48 -0700722#define M(T) [](void* op) { ((T*)op)->makeThreadsafe(); },
mtkleind559eb22016-08-11 07:08:28 -0700723static const void_fn make_threadsafe_fns[] = { TYPES(M) };
724#undef M
725
726// Older libstdc++ has pre-standard std::has_trivial_destructor.
727#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000)
728 template <typename T> using can_skip_destructor = std::has_trivial_destructor<T>;
729#else
730 template <typename T> using can_skip_destructor = std::is_trivially_destructible<T>;
731#endif
732
733// Most state ops (matrix, clip, save, restore) have a trivial destructor.
734#define M(T) !can_skip_destructor<T>::value ? [](void* op) { ((T*)op)->~T(); } : (void_fn)nullptr,
735static const void_fn dtor_fns[] = { TYPES(M) };
736#undef M
737
mtklein91cd2802016-08-17 11:39:48 -0700738void SkLiteDL::onDraw(SkCanvas* canvas) { this->map(draw_fns, canvas, canvas->getTotalMatrix()); }
739void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); }
mtklein03591a72016-08-07 13:35:46 -0700740
mtklein9c5052f2016-08-06 12:51:51 -0700741SkRect SkLiteDL::onGetBounds() {
742 return fBounds;
743}
744
mtklein883c8ef2016-08-16 09:36:18 -0700745SkLiteDL:: SkLiteDL(SkRect bounds) : fUsed(0), fReserved(0), fBounds(bounds) {}
mtklein765b6e62016-08-08 12:23:02 -0700746
mtklein883c8ef2016-08-16 09:36:18 -0700747SkLiteDL::~SkLiteDL() {
748 this->reset(SkRect::MakeEmpty());
749}
mtklein9c5052f2016-08-06 12:51:51 -0700750
751sk_sp<SkLiteDL> SkLiteDL::New(SkRect bounds) {
mtklein883c8ef2016-08-16 09:36:18 -0700752 return sk_sp<SkLiteDL>(new SkLiteDL(bounds));
mtklein9c5052f2016-08-06 12:51:51 -0700753}
754
mtklein883c8ef2016-08-16 09:36:18 -0700755void SkLiteDL::reset(SkRect bounds) {
756 SkASSERT(this->unique());
757 this->map(dtor_fns);
mtklein9c5052f2016-08-06 12:51:51 -0700758
mtklein883c8ef2016-08-16 09:36:18 -0700759 // Leave fBytes and fReserved alone.
760 fUsed = 0;
761 fBounds = bounds;
mtklein0c753e52016-08-09 07:40:23 -0700762}