SkLiteDL.cpp revision b25c3522446c9f84369dec2327ed9995fdb326de
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 "SkImageFilter.h" 12#include "SkLiteDL.h" 13#include "SkMath.h" 14#include "SkPicture.h" 15#include "SkRSXform.h" 16#include "SkTextBlob.h" 17 18#ifndef SKLITEDL_PAGE 19 #define SKLITEDL_PAGE 4096 20#endif 21 22// A stand-in for an optional SkRect which was not set, e.g. bounds for a saveLayer(). 23static const SkRect kUnset = { SK_ScalarInfinity, 0,0,0}; 24static const SkRect* maybe_unset(const SkRect& r) { 25 return r.left() == SK_ScalarInfinity ? nullptr : &r; 26} 27 28// copy_v(dst, src,n, src,n, ...) copies an arbitrary number of typed srcs into dst. 29static void copy_v(void* dst) {} 30 31template <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)...); 37} 38 39// Helper for getting back at arrays which have been copy_v'd together after an Op. 40template <typename D, typename T> 41static D* pod(T* op, size_t offset = 0) { 42 return SkTAddOffset<D>(op+1, offset); 43} 44 45// Pre-cache lazy non-threadsafe fields on SkPath and/or SkMatrix. 46static void make_threadsafe(SkPath* path, SkMatrix* matrix) { 47 if (path) { path->updateBoundsCache(); } 48 if (matrix) { (void)matrix->getType(); } 49} 50 51namespace { 52#define TYPES(M) \ 53 M(SetDrawFilter) M(Save) M(Restore) M(SaveLayer) \ 54 M(Concat) M(SetMatrix) M(Translate) M(TranslateZ) \ 55 M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \ 56 M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawRegion) M(DrawOval) M(DrawArc) \ 57 M(DrawRRect) M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \ 58 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 68 struct Op { 69 void makeThreadsafe() {} 70 71 uint32_t type : 8; 72 uint32_t skip : 24; 73 }; 74 static_assert(sizeof(Op) == 4, ""); 75 76 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 89 struct Save final : Op { 90 static const auto kType = Type::Save; 91 void draw(SkCanvas* c, const SkMatrix&) { c->save(); } 92 }; 93 struct Restore final : Op { 94 static const auto kType = Type::Restore; 95 void draw(SkCanvas* c, const SkMatrix&) { c->restore(); } 96 }; 97 struct SaveLayer final : Op { 98 static const auto kType = Type::SaveLayer; 99 SaveLayer(const SkRect* bounds, const SkPaint* paint, 100 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) { 101 if (bounds) { this->bounds = *bounds; } 102 if (paint) { this->paint = *paint; } 103 this->backdrop = sk_ref_sp(backdrop); 104 this->flags = flags; 105 } 106 SkRect bounds = kUnset; 107 SkPaint paint; 108 sk_sp<const SkImageFilter> backdrop; 109 SkCanvas::SaveLayerFlags flags; 110 void draw(SkCanvas* c, const SkMatrix&) { 111 c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags }); 112 } 113 }; 114 115 struct Concat final : Op { 116 static const auto kType = Type::Concat; 117 Concat(const SkMatrix& matrix) : matrix(matrix) {} 118 SkMatrix matrix; 119 void draw(SkCanvas* c, const SkMatrix&) { c->concat(matrix); } 120 void makeThreadsafe() { make_threadsafe(nullptr, &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) { 127 c->setMatrix(SkMatrix::Concat(original, matrix)); 128 } 129 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } 130 }; 131 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 }; 139 struct TranslateZ final : Op { 140 static const auto kType = Type::TranslateZ; 141 TranslateZ(SkScalar dz) : dz(dz) {} 142 SkScalar dz; 143 void draw(SkCanvas* c, const SkMatrix&) { 144 #ifdef SK_EXPERIMENTAL_SHADOWING 145 c->translateZ(dz); 146 #endif 147 } 148 }; 149 150 struct ClipPath final : Op { 151 static const auto kType = Type::ClipPath; 152 ClipPath(const SkPath& path, SkCanvas::ClipOp op, bool aa) : path(path), op(op), aa(aa) {} 153 SkPath path; 154 SkCanvas::ClipOp op; 155 bool aa; 156 void draw(SkCanvas* c, const SkMatrix&) { c->clipPath(path, op, aa); } 157 void makeThreadsafe() { make_threadsafe(&path, nullptr); } 158 }; 159 struct ClipRect final : Op { 160 static const auto kType = Type::ClipRect; 161 ClipRect(const SkRect& rect, SkCanvas::ClipOp op, bool aa) : rect(rect), op(op), aa(aa) {} 162 SkRect rect; 163 SkCanvas::ClipOp op; 164 bool aa; 165 void draw(SkCanvas* c, const SkMatrix&) { c->clipRect(rect, op, aa); } 166 }; 167 struct ClipRRect final : Op { 168 static const auto kType = Type::ClipRRect; 169 ClipRRect(const SkRRect& rrect, SkCanvas::ClipOp op, bool aa) : rrect(rrect), op(op), aa(aa) {} 170 SkRRect rrect; 171 SkCanvas::ClipOp op; 172 bool aa; 173 void draw(SkCanvas* c, const SkMatrix&) { c->clipRRect(rrect, op, aa); } 174 }; 175 struct ClipRegion final : Op { 176 static const auto kType = Type::ClipRegion; 177 ClipRegion(const SkRegion& region, SkCanvas::ClipOp op) : region(region), op(op) {} 178 SkRegion region; 179 SkCanvas::ClipOp op; 180 void draw(SkCanvas* c, const SkMatrix&) { c->clipRegion(region, op); } 181 }; 182 183 struct DrawPaint final : Op { 184 static const auto kType = Type::DrawPaint; 185 DrawPaint(const SkPaint& paint) : paint(paint) {} 186 SkPaint paint; 187 void draw(SkCanvas* c, const SkMatrix&) { c->drawPaint(paint); } 188 }; 189 struct DrawPath final : Op { 190 static const auto kType = Type::DrawPath; 191 DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {} 192 SkPath path; 193 SkPaint paint; 194 void draw(SkCanvas* c, const SkMatrix&) { c->drawPath(path, paint); } 195 void makeThreadsafe() { make_threadsafe(&path, nullptr); } 196 }; 197 struct DrawRect final : Op { 198 static const auto kType = Type::DrawRect; 199 DrawRect(const SkRect& rect, const SkPaint& paint) : rect(rect), paint(paint) {} 200 SkRect rect; 201 SkPaint paint; 202 void draw(SkCanvas* c, const SkMatrix&) { c->drawRect(rect, paint); } 203 }; 204 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 }; 211 struct DrawOval final : Op { 212 static const auto kType = Type::DrawOval; 213 DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {} 214 SkRect oval; 215 SkPaint paint; 216 void draw(SkCanvas* c, const SkMatrix&) { c->drawOval(oval, paint); } 217 }; 218 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 }; 232 struct DrawRRect final : Op { 233 static const auto kType = Type::DrawRRect; 234 DrawRRect(const SkRRect& rrect, const SkPaint& paint) : rrect(rrect), paint(paint) {} 235 SkRRect rrect; 236 SkPaint paint; 237 void draw(SkCanvas* c, const SkMatrix&) { c->drawRRect(rrect, paint); } 238 }; 239 struct DrawDRRect final : Op { 240 static const auto kType = Type::DrawDRRect; 241 DrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) 242 : outer(outer), inner(inner), paint(paint) {} 243 SkRRect outer, inner; 244 SkPaint paint; 245 void draw(SkCanvas* c, const SkMatrix&) { c->drawDRRect(outer, inner, paint); } 246 }; 247 248 struct DrawAnnotation final : Op { 249 static const auto kType = Type::DrawAnnotation; 250 DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {} 251 SkRect rect; 252 sk_sp<SkData> value; 253 void draw(SkCanvas* c, const SkMatrix&) { 254 c->drawAnnotation(rect, pod<char>(this), value.get()); 255 } 256 }; 257 struct DrawDrawable final : Op { 258 static const auto kType = Type::DrawDrawable; 259 DrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) : drawable(sk_ref_sp(drawable)) { 260 if (matrix) { this->matrix = *matrix; } 261 } 262 sk_sp<SkDrawable> drawable; 263 sk_sp<const SkPicture> snapped; 264 SkMatrix matrix = SkMatrix::I(); 265 void draw(SkCanvas* c, const SkMatrix&) { 266 snapped ? c->drawPicture(snapped.get(), &matrix, nullptr) 267 : c->drawDrawable(drawable.get(), &matrix); 268 } 269 void makeThreadsafe() { 270 snapped.reset(drawable->newPictureSnapshot()); 271 make_threadsafe(nullptr, &matrix); 272 } 273 }; 274 struct DrawPicture final : Op { 275 static const auto kType = Type::DrawPicture; 276 DrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) 277 : picture(sk_ref_sp(picture)) { 278 if (matrix) { this->matrix = *matrix; } 279 if (paint) { this->paint = *paint; has_paint = true; } 280 } 281 sk_sp<const SkPicture> picture; 282 SkMatrix matrix = SkMatrix::I(); 283 SkPaint paint; 284 bool has_paint = false; // TODO: why is a default paint not the same? 285 void draw(SkCanvas* c, const SkMatrix&) { 286 c->drawPicture(picture.get(), &matrix, has_paint ? &paint : nullptr); 287 } 288 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } 289 }; 290 struct DrawShadowedPicture final : Op { 291 static const auto kType = Type::DrawShadowedPicture; 292 DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, 293 const SkPaint* paint, const SkShadowParams& params) 294 : picture(sk_ref_sp(picture)) { 295 if (matrix) { this->matrix = *matrix; } 296 if (paint) { this->paint = *paint; } 297 this->params = params; 298 } 299 sk_sp<const SkPicture> picture; 300 SkMatrix matrix = SkMatrix::I(); 301 SkPaint paint; 302 SkShadowParams params; 303 void draw(SkCanvas* c, const SkMatrix&) { 304 #ifdef SK_EXPERIMENTAL_SHADOWING 305 c->drawShadowedPicture(picture.get(), &matrix, &paint, params); 306 #endif 307 } 308 void makeThreadsafe() { make_threadsafe(nullptr, &matrix); } 309 }; 310 311 struct DrawImage final : Op { 312 static const auto kType = Type::DrawImage; 313 DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint) 314 : image(std::move(image)), x(x), y(y) { 315 if (paint) { this->paint = *paint; } 316 } 317 sk_sp<const SkImage> image; 318 SkScalar x,y; 319 SkPaint paint; 320 void draw(SkCanvas* c, const SkMatrix&) { c->drawImage(image.get(), x,y, &paint); } 321 }; 322 struct DrawImageNine final : Op { 323 static const auto kType = Type::DrawImageNine; 324 DrawImageNine(sk_sp<const SkImage>&& image, 325 const SkIRect& center, const SkRect& dst, const SkPaint* paint) 326 : image(std::move(image)), center(center), dst(dst) { 327 if (paint) { this->paint = *paint; } 328 } 329 sk_sp<const SkImage> image; 330 SkIRect center; 331 SkRect dst; 332 SkPaint paint; 333 void draw(SkCanvas* c, const SkMatrix&) { 334 c->drawImageNine(image.get(), center, dst, &paint); 335 } 336 }; 337 struct DrawImageRect final : Op { 338 static const auto kType = Type::DrawImageRect; 339 DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst, 340 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) 341 : image(std::move(image)), dst(dst), constraint(constraint) { 342 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; 349 void draw(SkCanvas* c, const SkMatrix&) { 350 c->drawImageRect(image.get(), src, dst, &paint, constraint); 351 } 352 }; 353 struct DrawImageLattice final : Op { 354 static const auto kType = Type::DrawImageLattice; 355 DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs, 356 const SkIRect& src, const SkRect& dst, const SkPaint* paint) 357 : image(std::move(image)), xs(xs), ys(ys), fs(fs), src(src), dst(dst) { 358 if (paint) { this->paint = *paint; } 359 } 360 sk_sp<const SkImage> image; 361 int xs, ys, fs; 362 SkIRect src; 363 SkRect dst; 364 SkPaint paint; 365 void draw(SkCanvas* c, const SkMatrix&) { 366 auto xdivs = pod<int>(this, 0), 367 ydivs = pod<int>(this, xs*sizeof(int)); 368 auto flags = (0 == fs) ? nullptr : 369 pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int)); 370 c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src}, dst, &paint); 371 } 372 }; 373 374 struct DrawText final : Op { 375 static const auto kType = Type::DrawText; 376 DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint) 377 : bytes(bytes), x(x), y(y), paint(paint) {} 378 size_t bytes; 379 SkScalar x,y; 380 SkPaint paint; 381 void draw(SkCanvas* c, const SkMatrix&) { 382 c->drawText(pod<void>(this), bytes, x,y, paint); 383 } 384 }; 385 struct DrawPosText final : Op { 386 static const auto kType = Type::DrawPosText; 387 DrawPosText(size_t bytes, const SkPaint& paint, int n) 388 : bytes(bytes), paint(paint), n(n) {} 389 size_t bytes; 390 SkPaint paint; 391 int n; 392 void draw(SkCanvas* c, const SkMatrix&) { 393 auto points = pod<SkPoint>(this); 394 auto text = pod<void>(this, n*sizeof(SkPoint)); 395 c->drawPosText(text, bytes, points, paint); 396 } 397 }; 398 struct DrawPosTextH final : Op { 399 static const auto kType = Type::DrawPosTextH; 400 DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n) 401 : bytes(bytes), y(y), paint(paint), n(n) {} 402 size_t bytes; 403 SkScalar y; 404 SkPaint paint; 405 int n; 406 void draw(SkCanvas* c, const SkMatrix&) { 407 auto xs = pod<SkScalar>(this); 408 auto text = pod<void>(this, n*sizeof(SkScalar)); 409 c->drawPosTextH(text, bytes, xs, y, paint); 410 } 411 }; 412 struct DrawTextOnPath final : Op { 413 static const auto kType = Type::DrawTextOnPath; 414 DrawTextOnPath(size_t bytes, const SkPath& path, 415 const SkMatrix* matrix, const SkPaint& paint) 416 : bytes(bytes), path(path), paint(paint) { 417 if (matrix) { this->matrix = *matrix; } 418 } 419 size_t bytes; 420 SkPath path; 421 SkMatrix matrix = SkMatrix::I(); 422 SkPaint paint; 423 void draw(SkCanvas* c, const SkMatrix&) { 424 c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint); 425 } 426 void makeThreadsafe() { make_threadsafe(&path, &matrix); } 427 }; 428 struct DrawTextRSXform final : Op { 429 static const auto kType = Type::DrawTextRSXform; 430 DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint) 431 : bytes(bytes), paint(paint) { 432 if (cull) { this->cull = *cull; } 433 } 434 size_t bytes; 435 SkRect cull = kUnset; 436 SkPaint paint; 437 void draw(SkCanvas* c, const SkMatrix&) { 438 c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes), 439 maybe_unset(cull), paint); 440 } 441 }; 442 struct DrawTextBlob final : Op { 443 static const auto kType = Type::DrawTextBlob; 444 DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) 445 : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {} 446 sk_sp<const SkTextBlob> blob; 447 SkScalar x,y; 448 SkPaint paint; 449 void draw(SkCanvas* c, const SkMatrix&) { 450 c->drawTextBlob(blob.get(), x,y, paint); 451 } 452 }; 453 454 struct DrawPatch final : Op { 455 static const auto kType = Type::DrawPatch; 456 DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4], 457 SkXfermode* xfermode, const SkPaint& paint) 458 : xfermode(sk_ref_sp(xfermode)), paint(paint) { 459 copy_v(this->cubics, cubics, 12); 460 if (colors) { copy_v(this->colors, colors, 4); has_colors = true; } 461 if (texs ) { copy_v(this->texs , texs , 4); has_texs = true; } 462 } 463 SkPoint cubics[12]; 464 SkColor colors[4]; 465 SkPoint texs[4]; 466 sk_sp<SkXfermode> xfermode; 467 SkPaint paint; 468 bool has_colors = false; 469 bool has_texs = false; 470 void draw(SkCanvas* c, const SkMatrix&) { 471 c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr, 472 xfermode.get(), paint); 473 } 474 }; 475 struct DrawPoints final : Op { 476 static const auto kType = Type::DrawPoints; 477 DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint) 478 : mode(mode), count(count), paint(paint) {} 479 SkCanvas::PointMode mode; 480 size_t count; 481 SkPaint paint; 482 void draw(SkCanvas* c, const SkMatrix&) { 483 c->drawPoints(mode, count, pod<SkPoint>(this), paint); 484 } 485 }; 486 struct DrawVertices final : Op { 487 static const auto kType = Type::DrawVertices; 488 DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices, 489 const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices) 490 : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices) 491 , paint(paint), has_texs(has_texs), has_colors(has_colors), has_indices(has_indices) {} 492 SkCanvas::VertexMode mode; 493 int count; 494 sk_sp<SkXfermode> xfermode; 495 int nindices; 496 SkPaint paint; 497 bool has_texs; 498 bool has_colors; 499 bool has_indices; 500 void draw(SkCanvas* c, const SkMatrix&) { 501 SkPoint* vertices = pod<SkPoint>(this, 0); 502 size_t offset = count*sizeof(SkPoint); 503 504 SkPoint* texs = nullptr; 505 if (has_texs) { 506 texs = pod<SkPoint>(this, offset); 507 offset += count*sizeof(SkPoint); 508 } 509 510 SkColor* colors = nullptr; 511 if (has_colors) { 512 colors = pod<SkColor>(this, offset); 513 offset += count*sizeof(SkColor); 514 } 515 516 uint16_t* indices = nullptr; 517 if (has_indices) { 518 indices = pod<uint16_t>(this, offset); 519 } 520 c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(), 521 indices, nindices, paint); 522 } 523 }; 524 struct DrawAtlas final : Op { 525 static const auto kType = Type::DrawAtlas; 526 DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode, 527 const SkRect* cull, const SkPaint* paint, bool has_colors) 528 : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) { 529 if (cull) { this->cull = *cull; } 530 if (paint) { this->paint = *paint; } 531 } 532 sk_sp<const SkImage> atlas; 533 int count; 534 SkXfermode::Mode xfermode; 535 SkRect cull = kUnset; 536 SkPaint paint; 537 bool has_colors; 538 void draw(SkCanvas* c, const SkMatrix&) { 539 auto xforms = pod<SkRSXform>(this, 0); 540 auto texs = pod<SkRect>(this, count*sizeof(SkRSXform)); 541 auto colors = has_colors 542 ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect))) 543 : nullptr; 544 c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode, 545 maybe_unset(cull), &paint); 546 } 547 }; 548} 549 550template <typename T, typename... Args> 551void* SkLiteDL::push(size_t pod, Args&&... args) { 552 size_t skip = SkAlignPtr(sizeof(T) + pod); 553 SkASSERT(skip < (1<<24)); 554 if (fUsed + skip > fReserved) { 555 static_assert(SkIsPow2(SKLITEDL_PAGE), "This math needs updating for non-pow2."); 556 // Next greater multiple of SKLITEDL_PAGE. 557 fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE-1); 558 fBytes.realloc(fReserved); 559 } 560 SkASSERT(fUsed + skip <= fReserved); 561 auto op = (T*)(fBytes.get() + fUsed); 562 fUsed += skip; 563 new (op) T{ std::forward<Args>(args)... }; 564 op->type = (uint32_t)T::kType; 565 op->skip = skip; 566 return op+1; 567} 568 569template <typename Fn, typename... Args> 570inline void SkLiteDL::map(const Fn fns[], Args... args) { 571 auto end = fBytes.get() + fUsed; 572 for (uint8_t* ptr = fBytes.get(); ptr < end; ) { 573 auto op = (Op*)ptr; 574 auto type = op->type; 575 auto skip = op->skip; 576 if (auto fn = fns[type]) { // We replace no-op functions with nullptrs 577 fn(op, args...); // to avoid the overhead of a pointless call. 578 } 579 ptr += skip; 580 } 581} 582 583#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 584void SkLiteDL::setDrawFilter(SkDrawFilter* df) { 585 this->push<SetDrawFilter>(0, df); 586} 587#endif 588 589void SkLiteDL:: save() { this->push <Save>(0); } 590void SkLiteDL::restore() { this->push<Restore>(0); } 591void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint, 592 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) { 593 this->push<SaveLayer>(0, bounds, paint, backdrop, flags); 594} 595 596void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); } 597void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); } 598void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); } 599void SkLiteDL::translateZ(SkScalar dz) { this->push<TranslateZ>(0, dz); } 600 601void SkLiteDL::clipPath(const SkPath& path, SkCanvas::ClipOp op, bool aa) { 602 this->push<ClipPath>(0, path, op, aa); 603} 604void SkLiteDL::clipRect(const SkRect& rect, SkCanvas::ClipOp op, bool aa) { 605 this->push<ClipRect>(0, rect, op, aa); 606} 607void SkLiteDL::clipRRect(const SkRRect& rrect, SkCanvas::ClipOp op, bool aa) { 608 this->push<ClipRRect>(0, rrect, op, aa); 609} 610void SkLiteDL::clipRegion(const SkRegion& region, SkCanvas::ClipOp op) { 611 this->push<ClipRegion>(0, region, op); 612} 613 614void SkLiteDL::drawPaint(const SkPaint& paint) { 615 this->push<DrawPaint>(0, paint); 616} 617void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) { 618 this->push<DrawPath>(0, path, paint); 619} 620void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) { 621 this->push<DrawRect>(0, rect, paint); 622} 623void SkLiteDL::drawRegion(const SkRegion& region, const SkPaint& paint) { 624 this->push<DrawRegion>(0, region, paint); 625} 626void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) { 627 this->push<DrawOval>(0, oval, paint); 628} 629void SkLiteDL::drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, 630 const SkPaint& paint) { 631 this->push<DrawArc>(0, oval, startAngle, sweepAngle, useCenter, paint); 632} 633void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 634 this->push<DrawRRect>(0, rrect, paint); 635} 636void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 637 this->push<DrawDRRect>(0, outer, inner, paint); 638} 639 640void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) { 641 size_t bytes = strlen(key)+1; 642 void* pod = this->push<DrawAnnotation>(bytes, rect, value); 643 copy_v(pod, key,bytes); 644} 645void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { 646 this->push<DrawDrawable>(0, drawable, matrix); 647} 648void SkLiteDL::drawPicture(const SkPicture* picture, 649 const SkMatrix* matrix, const SkPaint* paint) { 650 this->push<DrawPicture>(0, picture, matrix, paint); 651} 652void SkLiteDL::drawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, 653 const SkPaint* paint, const SkShadowParams& params) { 654 push<DrawShadowedPicture>(0, picture, matrix, paint, params); 655} 656 657void SkLiteDL::drawImage(sk_sp<const SkImage> image, SkScalar x, SkScalar y, const SkPaint* paint) { 658 this->push<DrawImage>(0, std::move(image), x,y, paint); 659} 660void SkLiteDL::drawImageNine(sk_sp<const SkImage> image, const SkIRect& center, 661 const SkRect& dst, const SkPaint* paint) { 662 this->push<DrawImageNine>(0, std::move(image), center, dst, paint); 663} 664void SkLiteDL::drawImageRect(sk_sp<const SkImage> image, const SkRect* src, const SkRect& dst, 665 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { 666 this->push<DrawImageRect>(0, std::move(image), src, dst, paint, constraint); 667} 668void SkLiteDL::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice, 669 const SkRect& dst, const SkPaint* paint) { 670 int xs = lattice.fXCount, ys = lattice.fYCount; 671 int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0; 672 size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags); 673 SkASSERT(lattice.fBounds); 674 void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds, 675 dst, paint); 676 copy_v(pod, lattice.fXDivs, xs, 677 lattice.fYDivs, ys, 678 lattice.fFlags, fs); 679} 680 681void SkLiteDL::drawText(const void* text, size_t bytes, 682 SkScalar x, SkScalar y, const SkPaint& paint) { 683 void* pod = this->push<DrawText>(bytes, bytes, x, y, paint); 684 copy_v(pod, (const char*)text,bytes); 685} 686void SkLiteDL::drawPosText(const void* text, size_t bytes, 687 const SkPoint pos[], const SkPaint& paint) { 688 int n = paint.countText(text, bytes); 689 void* pod = this->push<DrawPosText>(n*sizeof(SkPoint)+bytes, bytes, paint, n); 690 copy_v(pod, pos,n, (const char*)text,bytes); 691} 692void SkLiteDL::drawPosTextH(const void* text, size_t bytes, 693 const SkScalar xs[], SkScalar y, const SkPaint& paint) { 694 int n = paint.countText(text, bytes); 695 void* pod = this->push<DrawPosTextH>(n*sizeof(SkScalar)+bytes, bytes, y, paint, n); 696 copy_v(pod, xs,n, (const char*)text,bytes); 697} 698void SkLiteDL::drawTextOnPath(const void* text, size_t bytes, 699 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { 700 void* pod = this->push<DrawTextOnPath>(bytes, bytes, path, matrix, paint); 701 copy_v(pod, (const char*)text,bytes); 702} 703void SkLiteDL::drawTextRSXform(const void* text, size_t bytes, 704 const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) { 705 int n = paint.countText(text, bytes); 706 void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, cull, paint); 707 copy_v(pod, (const char*)text,bytes, xforms,n); 708} 709void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { 710 this->push<DrawTextBlob>(0, blob, x,y, paint); 711} 712 713void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4], 714 SkXfermode* xfermode, const SkPaint& paint) { 715 this->push<DrawPatch>(0, points, colors, texs, xfermode, paint); 716} 717void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[], 718 const SkPaint& paint) { 719 void* pod = this->push<DrawPoints>(count*sizeof(SkPoint), mode, count, paint); 720 copy_v(pod, points,count); 721} 722void SkLiteDL::drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[], 723 const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode, 724 const uint16_t indices[], int nindices, const SkPaint& paint) { 725 size_t bytes = count * sizeof(SkPoint); 726 if (texs ) { bytes += count * sizeof(SkPoint); } 727 if (colors) { bytes += count * sizeof(SkColor); } 728 if (indices) { bytes += nindices * sizeof(uint16_t); } 729 void* pod = this->push<DrawVertices>(bytes, mode, count, xfermode, nindices, paint, 730 texs != nullptr, colors != nullptr, indices != nullptr); 731 copy_v(pod, vertices, count, 732 texs, texs ? count : 0, 733 colors, colors ? count : 0, 734 indices, indices ? nindices : 0); 735} 736void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[], 737 const SkColor colors[], int count, SkXfermode::Mode xfermode, 738 const SkRect* cull, const SkPaint* paint) { 739 size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect)); 740 if (colors) { 741 bytes += count*sizeof(SkColor); 742 } 743 void* pod = this->push<DrawAtlas>(bytes, 744 atlas, count, xfermode, cull, paint, colors != nullptr); 745 copy_v(pod, xforms, count, 746 texs, count, 747 colors, colors ? count : 0); 748} 749 750typedef void(*draw_fn)(void*, SkCanvas*, const SkMatrix&); 751typedef void(*void_fn)(void*); 752 753// All ops implement draw(). 754#define M(T) [](void* op, SkCanvas* c, const SkMatrix& original) { ((T*)op)->draw(c, original); }, 755static const draw_fn draw_fns[] = { TYPES(M) }; 756#undef M 757 758#define M(T) [](void* op) { ((T*)op)->makeThreadsafe(); }, 759static const void_fn make_threadsafe_fns[] = { TYPES(M) }; 760#undef M 761 762// Older libstdc++ has pre-standard std::has_trivial_destructor. 763#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000) 764 template <typename T> using can_skip_destructor = std::has_trivial_destructor<T>; 765#else 766 template <typename T> using can_skip_destructor = std::is_trivially_destructible<T>; 767#endif 768 769// Most state ops (matrix, clip, save, restore) have a trivial destructor. 770#define M(T) !can_skip_destructor<T>::value ? [](void* op) { ((T*)op)->~T(); } : (void_fn)nullptr, 771static const void_fn dtor_fns[] = { TYPES(M) }; 772#undef M 773 774void SkLiteDL::onDraw(SkCanvas* canvas) { this->map(draw_fns, canvas, canvas->getTotalMatrix()); } 775void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); } 776 777SkRect SkLiteDL::onGetBounds() { 778 return fBounds; 779} 780 781SkLiteDL:: SkLiteDL(SkRect bounds) : fUsed(0), fReserved(0), fBounds(bounds) {} 782 783SkLiteDL::~SkLiteDL() { 784 this->reset(SkRect::MakeEmpty()); 785} 786 787sk_sp<SkLiteDL> SkLiteDL::New(SkRect bounds) { 788 return sk_sp<SkLiteDL>(new SkLiteDL(bounds)); 789} 790 791void SkLiteDL::reset(SkRect bounds) { 792 SkASSERT(this->unique()); 793 this->map(dtor_fns); 794 795 // Leave fBytes and fReserved alone. 796 fUsed = 0; 797 fBounds = bounds; 798} 799 800void SkLiteDL::drawAsLayer(SkCanvas* canvas, const SkMatrix* matrix, const SkPaint* paint) { 801 auto fallback_plan = [&] { 802 SkRect bounds = this->getBounds(); 803 canvas->saveLayer(&bounds, paint); 804 this->draw(canvas, matrix); 805 canvas->restore(); 806 }; 807 808 // TODO: single-draw specializations 809 810 return fallback_plan(); 811} 812 813void SkLiteDL::setBounds(const SkRect& bounds) { 814 fBounds = bounds; 815} 816