1/* 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" 9#include "SkData.h" 10#include "SkDrawFilter.h" 11#include "SkDrawShadowRec.h" 12#include "SkImage.h" 13#include "SkImageFilter.h" 14#include "SkLiteDL.h" 15#include "SkMath.h" 16#include "SkPicture.h" 17#include "SkRegion.h" 18#include "SkRSXform.h" 19#include "SkTextBlob.h" 20#include "SkVertices.h" 21 22#ifndef SKLITEDL_PAGE 23 #define SKLITEDL_PAGE 4096 24#endif 25 26// A stand-in for an optional SkRect which was not set, e.g. bounds for a saveLayer(). 27static const SkRect kUnset = { SK_ScalarInfinity, 0,0,0}; 28static const SkRect* maybe_unset(const SkRect& r) { 29 return r.left() == SK_ScalarInfinity ? nullptr : &r; 30} 31 32// copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into dst. 33static void copy_v(void* dst) {} 34 35template <typename S, typename... Rest> 36static void copy_v(void* dst, const S* src, int n, Rest&&... rest) { 37 SkASSERTF(((uintptr_t)dst & (alignof(S)-1)) == 0, 38 "Expected %p to be aligned for at least %zu bytes.", dst, alignof(S)); 39 sk_careful_memcpy(dst, src, n*sizeof(S)); 40 copy_v(SkTAddOffset<void>(dst, n*sizeof(S)), std::forward<Rest>(rest)...); 41} 42 43// Helper for getting back at arrays which have been copy_v'd together after an Op. 44template <typename D, typename T> 45static const D* pod(const T* op, size_t offset = 0) { 46 return SkTAddOffset<const D>(op+1, offset); 47} 48 49namespace { 50#define TYPES(M) \ 51 M(SetDrawFilter) M(Save) M(Restore) M(SaveLayer) \ 52 M(Concat) M(SetMatrix) M(Translate) \ 53 M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \ 54 M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawRegion) M(DrawOval) M(DrawArc) \ 55 M(DrawRRect) M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \ 56 M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) \ 57 M(DrawText) M(DrawPosText) M(DrawPosTextH) \ 58 M(DrawTextOnPath) M(DrawTextRSXform) M(DrawTextBlob) \ 59 M(DrawPatch) M(DrawPoints) M(DrawVertices) M(DrawAtlas) M(DrawShadowRec) 60 61#define M(T) T, 62 enum class Type : uint8_t { TYPES(M) }; 63#undef M 64 65 struct Op { 66 uint32_t type : 8; 67 uint32_t skip : 24; 68 }; 69 static_assert(sizeof(Op) == 4, ""); 70 71 struct SetDrawFilter final : Op { 72#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 73 static const auto kType = Type::SetDrawFilter; 74 SetDrawFilter(SkDrawFilter* df) : drawFilter(sk_ref_sp(df)) {} 75 sk_sp<SkDrawFilter> drawFilter; 76#endif 77 void draw(SkCanvas* c, const SkMatrix&) const { 78#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 79 c->setDrawFilter(drawFilter.get()); 80#endif 81 } 82 }; 83 84 struct Save final : Op { 85 static const auto kType = Type::Save; 86 void draw(SkCanvas* c, const SkMatrix&) const { c->save(); } 87 }; 88 struct Restore final : Op { 89 static const auto kType = Type::Restore; 90 void draw(SkCanvas* c, const SkMatrix&) const { c->restore(); } 91 }; 92 struct SaveLayer final : Op { 93 static const auto kType = Type::SaveLayer; 94 SaveLayer(const SkRect* bounds, const SkPaint* paint, 95 const SkImageFilter* backdrop, const SkImage* clipMask, 96 const SkMatrix* clipMatrix, SkCanvas::SaveLayerFlags flags) { 97 if (bounds) { this->bounds = *bounds; } 98 if (paint) { this->paint = *paint; } 99 this->backdrop = sk_ref_sp(backdrop); 100 this->clipMask = sk_ref_sp(clipMask); 101 this->clipMatrix = clipMatrix ? *clipMatrix : SkMatrix::I(); 102 this->flags = flags; 103 } 104 SkRect bounds = kUnset; 105 SkPaint paint; 106 sk_sp<const SkImageFilter> backdrop; 107 sk_sp<const SkImage> clipMask; 108 SkMatrix clipMatrix; 109 SkCanvas::SaveLayerFlags flags; 110 void draw(SkCanvas* c, const SkMatrix&) const { 111 c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), clipMask.get(), 112 clipMatrix.isIdentity() ? nullptr : &clipMatrix, flags }); 113 } 114 }; 115 116 struct Concat final : Op { 117 static const auto kType = Type::Concat; 118 Concat(const SkMatrix& matrix) : matrix(matrix) {} 119 SkMatrix matrix; 120 void draw(SkCanvas* c, const SkMatrix&) const { c->concat(matrix); } 121 }; 122 struct SetMatrix final : Op { 123 static const auto kType = Type::SetMatrix; 124 SetMatrix(const SkMatrix& matrix) : matrix(matrix) {} 125 SkMatrix matrix; 126 void draw(SkCanvas* c, const SkMatrix& original) const { 127 c->setMatrix(SkMatrix::Concat(original, matrix)); 128 } 129 }; 130 struct Translate final : Op { 131 static const auto kType = Type::Translate; 132 Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {} 133 SkScalar dx,dy; 134 void draw(SkCanvas* c, const SkMatrix&) const { 135 c->translate(dx, dy); 136 } 137 }; 138 139 struct ClipPath final : Op { 140 static const auto kType = Type::ClipPath; 141 ClipPath(const SkPath& path, SkClipOp op, bool aa) : path(path), op(op), aa(aa) {} 142 SkPath path; 143 SkClipOp op; 144 bool aa; 145 void draw(SkCanvas* c, const SkMatrix&) const { c->clipPath(path, op, aa); } 146 }; 147 struct ClipRect final : Op { 148 static const auto kType = Type::ClipRect; 149 ClipRect(const SkRect& rect, SkClipOp op, bool aa) : rect(rect), op(op), aa(aa) {} 150 SkRect rect; 151 SkClipOp op; 152 bool aa; 153 void draw(SkCanvas* c, const SkMatrix&) const { c->clipRect(rect, op, aa); } 154 }; 155 struct ClipRRect final : Op { 156 static const auto kType = Type::ClipRRect; 157 ClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) : rrect(rrect), op(op), aa(aa) {} 158 SkRRect rrect; 159 SkClipOp op; 160 bool aa; 161 void draw(SkCanvas* c, const SkMatrix&) const { c->clipRRect(rrect, op, aa); } 162 }; 163 struct ClipRegion final : Op { 164 static const auto kType = Type::ClipRegion; 165 ClipRegion(const SkRegion& region, SkClipOp op) : region(region), op(op) {} 166 SkRegion region; 167 SkClipOp op; 168 void draw(SkCanvas* c, const SkMatrix&) const { c->clipRegion(region, op); } 169 }; 170 171 struct DrawPaint final : Op { 172 static const auto kType = Type::DrawPaint; 173 DrawPaint(const SkPaint& paint) : paint(paint) {} 174 SkPaint paint; 175 void draw(SkCanvas* c, const SkMatrix&) const { c->drawPaint(paint); } 176 }; 177 struct DrawPath final : Op { 178 static const auto kType = Type::DrawPath; 179 DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {} 180 SkPath path; 181 SkPaint paint; 182 void draw(SkCanvas* c, const SkMatrix&) const { c->drawPath(path, paint); } 183 }; 184 struct DrawRect final : Op { 185 static const auto kType = Type::DrawRect; 186 DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {} 187 SkRect rect; 188 SkPaint paint; 189 void draw(SkCanvas* c, const SkMatrix&) const { c->drawRect(rect, paint); } 190 }; 191 struct DrawRegion final : Op { 192 static const auto kType = Type::DrawRegion; 193 DrawRegion(const SkRegion& region, const SkPaint& paint) : region(region), paint(paint) {} 194 SkRegion region; 195 SkPaint paint; 196 void draw(SkCanvas* c, const SkMatrix&) const { c->drawRegion(region, paint); } 197 }; 198 struct DrawOval final : Op { 199 static const auto kType = Type::DrawOval; 200 DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {} 201 SkRect oval; 202 SkPaint paint; 203 void draw(SkCanvas* c, const SkMatrix&) const { c->drawOval(oval, paint); } 204 }; 205 struct DrawArc final : Op { 206 static const auto kType = Type::DrawArc; 207 DrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, 208 const SkPaint& paint) 209 : oval(oval), startAngle(startAngle), sweepAngle(sweepAngle), useCenter(useCenter) 210 , paint(paint) {} 211 SkRect oval; 212 SkScalar startAngle; 213 SkScalar sweepAngle; 214 bool useCenter; 215 SkPaint paint; 216 void draw(SkCanvas* c, const SkMatrix&) const { c->drawArc(oval, startAngle, sweepAngle, 217 useCenter, paint); } 218 }; 219 struct DrawRRect final : Op { 220 static const auto kType = Type::DrawRRect; 221 DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {} 222 SkRRect rrect; 223 SkPaint paint; 224 void draw(SkCanvas* c, const SkMatrix&) const { c->drawRRect(rrect, paint); } 225 }; 226 struct DrawDRRect final : Op { 227 static const auto kType = Type::DrawDRRect; 228 DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) 229 : outer(outer), inner(inner), paint(paint) {} 230 SkRRect outer, inner; 231 SkPaint paint; 232 void draw(SkCanvas* c, const SkMatrix&) const { c->drawDRRect(outer, inner, paint); } 233 }; 234 235 struct DrawAnnotation final : Op { 236 static const auto kType = Type::DrawAnnotation; 237 DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {} 238 SkRect rect; 239 sk_sp<SkData> value; 240 void draw(SkCanvas* c, const SkMatrix&) const { 241 c->drawAnnotation(rect, pod<char>(this), value.get()); 242 } 243 }; 244 struct DrawDrawable final : Op { 245 static const auto kType = Type::DrawDrawable; 246 DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) { 247 if (matrix) { this->matrix = *matrix; } 248 } 249 sk_sp<SkDrawable> drawable; 250 SkMatrix matrix = SkMatrix::I(); 251 void draw(SkCanvas* c, const SkMatrix&) const { 252 c->drawDrawable(drawable.get(), &matrix); 253 } 254 }; 255 struct DrawPicture final : Op { 256 static const auto kType = Type::DrawPicture; 257 DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) 258 : picture(sk_ref_sp(picture)) { 259 if (matrix) { this->matrix = *matrix; } 260 if (paint) { this->paint = *paint; has_paint = true; } 261 } 262 sk_sp<const SkPicture> picture; 263 SkMatrix matrix = SkMatrix::I(); 264 SkPaint paint; 265 bool has_paint = false; // TODO: why is a default paint not the same? 266 void draw(SkCanvas* c, const SkMatrix&) const { 267 c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr); 268 } 269 }; 270 271 struct DrawImage final : Op { 272 static const auto kType = Type::DrawImage; 273 DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint) 274 : image(std::move(image)), x(x), y(y) { 275 if (paint) { this->paint = *paint; } 276 } 277 sk_sp<const SkImage> image; 278 SkScalar x,y; 279 SkPaint paint; 280 void draw(SkCanvas* c, const SkMatrix&) const { c->drawImage(image.get(), x,y, &paint); } 281 }; 282 struct DrawImageNine final : Op { 283 static const auto kType = Type::DrawImageNine; 284 DrawImageNine(sk_sp<const SkImage>&& image, 285 const SkIRect& center, const SkRect& dst, const SkPaint* paint) 286 : image(std::move(image)), center(center), dst(dst) { 287 if (paint) { this->paint = *paint; } 288 } 289 sk_sp<const SkImage> image; 290 SkIRect center; 291 SkRect dst; 292 SkPaint paint; 293 void draw(SkCanvas* c, const SkMatrix&) const { 294 c->drawImageNine(image.get(), center, dst, &paint); 295 } 296 }; 297 struct DrawImageRect final : Op { 298 static const auto kType = Type::DrawImageRect; 299 DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst, 300 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) 301 : image(std::move(image)), dst(dst), constraint(constraint) { 302 this->src = src ? *src : SkRect::MakeIWH(image->width(), image->height()); 303 if (paint) { this->paint = *paint; } 304 } 305 sk_sp<const SkImage> image; 306 SkRect src, dst; 307 SkPaint paint; 308 SkCanvas::SrcRectConstraint constraint; 309 void draw(SkCanvas* c, const SkMatrix&) const { 310 c->drawImageRect(image.get(), src, dst, &paint, constraint); 311 } 312 }; 313 struct DrawImageLattice final : Op { 314 static const auto kType = Type::DrawImageLattice; 315 DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs, 316 const SkIRect& src, const SkRect& dst, const SkPaint* paint) 317 : image(std::move(image)), xs(xs), ys(ys), fs(fs), src(src), dst(dst) { 318 if (paint) { this->paint = *paint; } 319 } 320 sk_sp<const SkImage> image; 321 int xs, ys, fs; 322 SkIRect src; 323 SkRect dst; 324 SkPaint paint; 325 void draw(SkCanvas* c, const SkMatrix&) const { 326 auto xdivs = pod<int>(this, 0), 327 ydivs = pod<int>(this, xs*sizeof(int)); 328 auto flags = (0 == fs) ? nullptr : 329 pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int)); 330 c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src}, dst, &paint); 331 } 332 }; 333 334 struct DrawText final : Op { 335 static const auto kType = Type::DrawText; 336 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; 341 void draw(SkCanvas* c, const SkMatrix&) const { 342 c->drawText(pod<void>(this), bytes, x,y, paint); 343 } 344 }; 345 struct DrawPosText final : Op { 346 static const auto kType = Type::DrawPosText; 347 DrawPosText(size_t bytes, const SkPaint& paint, int n) 348 : bytes(bytes), paint(paint), n(n) {} 349 size_t bytes; 350 SkPaint paint; 351 int n; 352 void draw(SkCanvas* c, const SkMatrix&) const { 353 auto points = pod<SkPoint>(this); 354 auto text = pod<void>(this, n*sizeof(SkPoint)); 355 c->drawPosText(text, bytes, points, paint); 356 } 357 }; 358 struct DrawPosTextH final : Op { 359 static const auto kType = Type::DrawPosTextH; 360 DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n) 361 : bytes(bytes), y(y), paint(paint), n(n) {} 362 size_t bytes; 363 SkScalar y; 364 SkPaint paint; 365 int n; 366 void draw(SkCanvas* c, const SkMatrix&) const { 367 auto xs = pod<SkScalar>(this); 368 auto text = pod<void>(this, n*sizeof(SkScalar)); 369 c->drawPosTextH(text, bytes, xs, y, paint); 370 } 371 }; 372 struct DrawTextOnPath final : Op { 373 static const auto kType = Type::DrawTextOnPath; 374 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; 383 void draw(SkCanvas* c, const SkMatrix&) const { 384 c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint); 385 } 386 }; 387 struct DrawTextRSXform final : Op { 388 static const auto kType = Type::DrawTextRSXform; 389 DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint) 390 : bytes(bytes), paint(paint) { 391 if (cull) { this->cull = *cull; } 392 } 393 size_t bytes; 394 SkRect cull = kUnset; 395 SkPaint paint; 396 void draw(SkCanvas* c, const SkMatrix&) const { 397 c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes), 398 maybe_unset(cull), paint); 399 } 400 }; 401 struct DrawTextBlob final : Op { 402 static const auto kType = Type::DrawTextBlob; 403 DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) 404 : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {} 405 sk_sp<const SkTextBlob> blob; 406 SkScalar x,y; 407 SkPaint paint; 408 void draw(SkCanvas* c, const SkMatrix&) const { 409 c->drawTextBlob(blob.get(), x,y, paint); 410 } 411 }; 412 413 struct DrawPatch final : Op { 414 static const auto kType = Type::DrawPatch; 415 DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4], 416 SkBlendMode bmode, const SkPaint& paint) 417 : xfermode(bmode), paint(paint) 418 { 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 SkBlendMode xfermode; 427 SkPaint paint; 428 bool has_colors = false; 429 bool has_texs = false; 430 void draw(SkCanvas* c, const SkMatrix&) const { 431 c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr, 432 xfermode, paint); 433 } 434 }; 435 struct DrawPoints final : Op { 436 static const auto kType = Type::DrawPoints; 437 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; 442 void draw(SkCanvas* c, const SkMatrix&) const { 443 c->drawPoints(mode, count, pod<SkPoint>(this), paint); 444 } 445 }; 446 struct DrawVertices final : Op { 447 static const auto kType = Type::DrawVertices; 448 DrawVertices(const SkVertices* v, SkBlendMode m, const SkPaint& p) 449 : vertices(sk_ref_sp(const_cast<SkVertices*>(v))), mode(m), paint(p) {} 450 sk_sp<SkVertices> vertices; 451 SkBlendMode mode; 452 SkPaint paint; 453 void draw(SkCanvas* c, const SkMatrix&) const { 454 c->drawVertices(vertices, mode, paint); 455 } 456 }; 457 struct DrawAtlas final : Op { 458 static const auto kType = Type::DrawAtlas; 459 DrawAtlas(const SkImage* atlas, int count, SkBlendMode xfermode, 460 const SkRect* cull, const SkPaint* paint, bool has_colors) 461 : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) { 462 if (cull) { this->cull = *cull; } 463 if (paint) { this->paint = *paint; } 464 } 465 sk_sp<const SkImage> atlas; 466 int count; 467 SkBlendMode xfermode; 468 SkRect cull = kUnset; 469 SkPaint paint; 470 bool has_colors; 471 void draw(SkCanvas* c, const SkMatrix&) const { 472 auto xforms = pod<SkRSXform>(this, 0); 473 auto texs = pod<SkRect>(this, count*sizeof(SkRSXform)); 474 auto colors = has_colors 475 ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect))) 476 : nullptr; 477 c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode, 478 maybe_unset(cull), &paint); 479 } 480 }; 481 struct DrawShadowRec final : Op { 482 static const auto kType = Type::DrawShadowRec; 483 DrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) 484 : fPath(path), fRec(rec) 485 {} 486 SkPath fPath; 487 SkDrawShadowRec fRec; 488 void draw(SkCanvas* c, const SkMatrix&) const { 489 c->private_draw_shadow_rec(fPath, fRec); 490 } 491 }; 492} 493 494template <typename T, typename... Args> 495void* SkLiteDL::push(size_t pod, Args&&... args) { 496 size_t skip = SkAlignPtr(sizeof(T) + pod); 497 SkASSERT(skip < (1<<24)); 498 if (fUsed + skip > fReserved) { 499 static_assert(SkIsPow2(SKLITEDL_PAGE), "This math needs updating for non-pow2."); 500 // Next greater multiple of SKLITEDL_PAGE. 501 fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE-1); 502 fBytes.realloc(fReserved); 503 } 504 SkASSERT(fUsed + skip <= fReserved); 505 auto op = (T*)(fBytes.get() + fUsed); 506 fUsed += skip; 507 new (op) T{ std::forward<Args>(args)... }; 508 op->type = (uint32_t)T::kType; 509 op->skip = skip; 510 return op+1; 511} 512 513template <typename Fn, typename... Args> 514inline void SkLiteDL::map(const Fn fns[], Args... args) const { 515 auto end = fBytes.get() + fUsed; 516 for (const uint8_t* ptr = fBytes.get(); ptr < end; ) { 517 auto op = (const Op*)ptr; 518 auto type = op->type; 519 auto skip = op->skip; 520 if (auto fn = fns[type]) { // We replace no-op functions with nullptrs 521 fn(op, args...); // to avoid the overhead of a pointless call. 522 } 523 ptr += skip; 524 } 525} 526 527#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 528void SkLiteDL::setDrawFilter(SkDrawFilter* df) { 529 this->push<SetDrawFilter>(0, df); 530} 531#endif 532 533void SkLiteDL:: save() { this->push <Save>(0); } 534void SkLiteDL::restore() { this->push<Restore>(0); } 535void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint, 536 const SkImageFilter* backdrop, const SkImage* clipMask, 537 const SkMatrix* clipMatrix, SkCanvas::SaveLayerFlags flags) { 538 this->push<SaveLayer>(0, bounds, paint, backdrop, clipMask, clipMatrix, flags); 539} 540 541void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); } 542void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); } 543void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); } 544 545void SkLiteDL::clipPath(const SkPath& path, SkClipOp op, bool aa) { 546 this->push<ClipPath>(0, path, op, aa); 547} 548void SkLiteDL::clipRect(const SkRect& rect, SkClipOp op, bool aa) { 549 this->push<ClipRect>(0, rect, op, aa); 550} 551void SkLiteDL::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { 552 this->push<ClipRRect>(0, rrect, op, aa); 553} 554void SkLiteDL::clipRegion(const SkRegion& region, SkClipOp op) { 555 this->push<ClipRegion>(0, region, op); 556} 557 558void SkLiteDL::drawPaint(const SkPaint& paint) { 559 this->push<DrawPaint>(0, paint); 560} 561void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) { 562 this->push<DrawPath>(0, path, paint); 563} 564void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) { 565 this->push<DrawRect>(0, rect, paint); 566} 567void SkLiteDL::drawRegion(const SkRegion& region, const SkPaint& paint) { 568 this->push<DrawRegion>(0, region, paint); 569} 570void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) { 571 this->push<DrawOval>(0, oval, paint); 572} 573void SkLiteDL::drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, 574 const SkPaint& paint) { 575 this->push<DrawArc>(0, oval, startAngle, sweepAngle, useCenter, paint); 576} 577void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 578 this->push<DrawRRect>(0, rrect, paint); 579} 580void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 581 this->push<DrawDRRect>(0, outer, inner, paint); 582} 583 584void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) { 585 size_t bytes = strlen(key)+1; 586 void* pod = this->push<DrawAnnotation>(bytes, rect, value); 587 copy_v(pod, key,bytes); 588} 589void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { 590 this->push<DrawDrawable>(0, drawable, matrix); 591} 592void SkLiteDL::drawPicture(const SkPicture* picture, 593 const SkMatrix* matrix, const SkPaint* paint) { 594 this->push<DrawPicture>(0, picture, matrix, paint); 595} 596void SkLiteDL::drawImage(sk_sp<const SkImage> image, SkScalar x, SkScalar y, const SkPaint* paint) { 597 this->push<DrawImage>(0, std::move(image), x,y, paint); 598} 599void SkLiteDL::drawImageNine(sk_sp<const SkImage> image, const SkIRect& center, 600 const SkRect& dst, const SkPaint* paint) { 601 this->push<DrawImageNine>(0, std::move(image), center, dst, paint); 602} 603void SkLiteDL::drawImageRect(sk_sp<const SkImage> image, const SkRect* src, const SkRect& dst, 604 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { 605 this->push<DrawImageRect>(0, std::move(image), src, dst, paint, constraint); 606} 607void SkLiteDL::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice, 608 const SkRect& dst, const SkPaint* paint) { 609 int xs = lattice.fXCount, ys = lattice.fYCount; 610 int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0; 611 size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags); 612 SkASSERT(lattice.fBounds); 613 void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds, 614 dst, paint); 615 copy_v(pod, lattice.fXDivs, xs, 616 lattice.fYDivs, ys, 617 lattice.fFlags, fs); 618} 619 620void SkLiteDL::drawText(const void* text, size_t bytes, 621 SkScalar x, SkScalar y, const SkPaint& paint) { 622 void* pod = this->push<DrawText>(bytes, bytes, x, y, paint); 623 copy_v(pod, (const char*)text,bytes); 624} 625void SkLiteDL::drawPosText(const void* text, size_t bytes, 626 const SkPoint pos[], const SkPaint& paint) { 627 int n = paint.countText(text, bytes); 628 void* pod = this->push<DrawPosText>(n*sizeof(SkPoint)+bytes, bytes, paint, n); 629 copy_v(pod, pos,n, (const char*)text,bytes); 630} 631void SkLiteDL::drawPosTextH(const void* text, size_t bytes, 632 const SkScalar xs[], SkScalar y, const SkPaint& paint) { 633 int n = paint.countText(text, bytes); 634 void* pod = this->push<DrawPosTextH>(n*sizeof(SkScalar)+bytes, bytes, y, paint, n); 635 copy_v(pod, xs,n, (const char*)text,bytes); 636} 637void SkLiteDL::drawTextOnPath(const void* text, size_t bytes, 638 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { 639 void* pod = this->push<DrawTextOnPath>(bytes, bytes, path, matrix, paint); 640 copy_v(pod, (const char*)text,bytes); 641} 642void SkLiteDL::drawTextRSXform(const void* text, size_t bytes, 643 const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) { 644 int n = paint.countText(text, bytes); 645 void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, cull, paint); 646 copy_v(pod, (const char*)text,bytes, xforms,n); 647} 648void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { 649 this->push<DrawTextBlob>(0, blob, x,y, paint); 650} 651 652void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4], 653 SkBlendMode bmode, const SkPaint& paint) { 654 this->push<DrawPatch>(0, points, colors, texs, bmode, paint); 655} 656void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[], 657 const SkPaint& paint) { 658 void* pod = this->push<DrawPoints>(count*sizeof(SkPoint), mode, count, paint); 659 copy_v(pod, points,count); 660} 661void SkLiteDL::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { 662 this->push<DrawVertices>(0, vertices, mode, paint); 663} 664void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[], 665 const SkColor colors[], int count, SkBlendMode xfermode, 666 const SkRect* cull, const SkPaint* paint) { 667 size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect)); 668 if (colors) { 669 bytes += count*sizeof(SkColor); 670 } 671 void* pod = this->push<DrawAtlas>(bytes, 672 atlas, count, xfermode, cull, paint, colors != nullptr); 673 copy_v(pod, xforms, count, 674 texs, count, 675 colors, colors ? count : 0); 676} 677void SkLiteDL::drawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { 678 this->push<DrawShadowRec>(0, path, rec); 679} 680 681typedef void(*draw_fn)(const void*, SkCanvas*, const SkMatrix&); 682typedef void(*void_fn)(const void*); 683 684// All ops implement draw(). 685#define M(T) [](const void* op, SkCanvas* c, const SkMatrix& original) { \ 686 ((const T*)op)->draw(c, original); \ 687}, 688static const draw_fn draw_fns[] = { TYPES(M) }; 689#undef M 690 691// Older libstdc++ has pre-standard std::has_trivial_destructor. 692#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000) 693 template <typename T> using can_skip_destructor = std::has_trivial_destructor<T>; 694#else 695 template <typename T> using can_skip_destructor = std::is_trivially_destructible<T>; 696#endif 697 698// Most state ops (matrix, clip, save, restore) have a trivial destructor. 699#define M(T) !can_skip_destructor<T>::value ? [](const void* op) { ((const T*)op)->~T(); } \ 700 : (void_fn)nullptr, 701static const void_fn dtor_fns[] = { TYPES(M) }; 702#undef M 703 704void SkLiteDL::draw(SkCanvas* canvas) const { 705 SkAutoCanvasRestore acr(canvas, false); 706 this->map(draw_fns, canvas, canvas->getTotalMatrix()); 707} 708 709SkLiteDL::~SkLiteDL() { 710 this->reset(); 711} 712 713void SkLiteDL::reset() { 714 this->map(dtor_fns); 715 716 // Leave fBytes and fReserved alone. 717 fUsed = 0; 718} 719