SkLiteDL.cpp revision 0764efe6a9ae65ad83992f614f57ca9db5b1f191
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, SkRegion::Op op, bool aa) : path(path), op(op), aa(aa) {} 153 SkPath path; 154 SkRegion::Op 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, SkRegion::Op op, bool aa) : rect(rect), op(op), aa(aa) {} 162 SkRect rect; 163 SkRegion::Op 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, SkRegion::Op op, bool aa) : rrect(rrect), op(op), aa(aa) {} 170 SkRRect rrect; 171 SkRegion::Op 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, SkRegion::Op op) : region(region), op(op) {} 178 SkRegion region; 179 SkRegion::Op 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 SkRect& dst, const SkPaint* paint) 357 : image(std::move(image)), xs(xs), ys(ys), fs(fs), dst(dst) { 358 if (paint) { this->paint = *paint; } 359 } 360 sk_sp<const SkImage> image; 361 int xs, ys, fs; 362 SkRect dst; 363 SkPaint paint; 364 void draw(SkCanvas* c, const SkMatrix&) { 365 auto xdivs = pod<int>(this, 0), 366 ydivs = pod<int>(this, xs*sizeof(int)); 367 auto flags = (0 == fs) ? nullptr : 368 pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int)); 369 c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys}, dst, &paint); 370 } 371 }; 372 373 struct DrawText final : Op { 374 static const auto kType = Type::DrawText; 375 DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint) 376 : bytes(bytes), x(x), y(y), paint(paint) {} 377 size_t bytes; 378 SkScalar x,y; 379 SkPaint paint; 380 void draw(SkCanvas* c, const SkMatrix&) { 381 c->drawText(pod<void>(this), bytes, x,y, paint); 382 } 383 }; 384 struct DrawPosText final : Op { 385 static const auto kType = Type::DrawPosText; 386 DrawPosText(size_t bytes, const SkPaint& paint, int n) 387 : bytes(bytes), paint(paint), n(n) {} 388 size_t bytes; 389 SkPaint paint; 390 int n; 391 void draw(SkCanvas* c, const SkMatrix&) { 392 auto points = pod<SkPoint>(this); 393 auto text = pod<void>(this, n*sizeof(SkPoint)); 394 c->drawPosText(text, bytes, points, paint); 395 } 396 }; 397 struct DrawPosTextH final : Op { 398 static const auto kType = Type::DrawPosTextH; 399 DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n) 400 : bytes(bytes), y(y), paint(paint), n(n) {} 401 size_t bytes; 402 SkScalar y; 403 SkPaint paint; 404 int n; 405 void draw(SkCanvas* c, const SkMatrix&) { 406 auto xs = pod<SkScalar>(this); 407 auto text = pod<void>(this, n*sizeof(SkScalar)); 408 c->drawPosTextH(text, bytes, xs, y, paint); 409 } 410 }; 411 struct DrawTextOnPath final : Op { 412 static const auto kType = Type::DrawTextOnPath; 413 DrawTextOnPath(size_t bytes, const SkPath& path, 414 const SkMatrix* matrix, const SkPaint& paint) 415 : bytes(bytes), path(path), paint(paint) { 416 if (matrix) { this->matrix = *matrix; } 417 } 418 size_t bytes; 419 SkPath path; 420 SkMatrix matrix = SkMatrix::I(); 421 SkPaint paint; 422 void draw(SkCanvas* c, const SkMatrix&) { 423 c->drawTextOnPath(pod<void>(this), bytes, path, &matrix, paint); 424 } 425 void makeThreadsafe() { make_threadsafe(&path, &matrix); } 426 }; 427 struct DrawTextRSXform final : Op { 428 static const auto kType = Type::DrawTextRSXform; 429 DrawTextRSXform(size_t bytes, const SkRect* cull, const SkPaint& paint) 430 : bytes(bytes), paint(paint) { 431 if (cull) { this->cull = *cull; } 432 } 433 size_t bytes; 434 SkRect cull = kUnset; 435 SkPaint paint; 436 void draw(SkCanvas* c, const SkMatrix&) { 437 c->drawTextRSXform(pod<void>(this), bytes, pod<SkRSXform>(this, bytes), 438 maybe_unset(cull), paint); 439 } 440 }; 441 struct DrawTextBlob final : Op { 442 static const auto kType = Type::DrawTextBlob; 443 DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) 444 : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {} 445 sk_sp<const SkTextBlob> blob; 446 SkScalar x,y; 447 SkPaint paint; 448 void draw(SkCanvas* c, const SkMatrix&) { 449 c->drawTextBlob(blob.get(), x,y, paint); 450 } 451 }; 452 453 struct DrawPatch final : Op { 454 static const auto kType = Type::DrawPatch; 455 DrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4], 456 SkXfermode* xfermode, const SkPaint& paint) 457 : xfermode(sk_ref_sp(xfermode)), paint(paint) { 458 copy_v(this->cubics, cubics, 12); 459 if (colors) { copy_v(this->colors, colors, 4); has_colors = true; } 460 if (texs ) { copy_v(this->texs , texs , 4); has_texs = true; } 461 } 462 SkPoint cubics[12]; 463 SkColor colors[4]; 464 SkPoint texs[4]; 465 sk_sp<SkXfermode> xfermode; 466 SkPaint paint; 467 bool has_colors = false; 468 bool has_texs = false; 469 void draw(SkCanvas* c, const SkMatrix&) { 470 c->drawPatch(cubics, has_colors ? colors : nullptr, has_texs ? texs : nullptr, 471 xfermode.get(), paint); 472 } 473 }; 474 struct DrawPoints final : Op { 475 static const auto kType = Type::DrawPoints; 476 DrawPoints(SkCanvas::PointMode mode, size_t count, const SkPaint& paint) 477 : mode(mode), count(count), paint(paint) {} 478 SkCanvas::PointMode mode; 479 size_t count; 480 SkPaint paint; 481 void draw(SkCanvas* c, const SkMatrix&) { 482 c->drawPoints(mode, count, pod<SkPoint>(this), paint); 483 } 484 }; 485 struct DrawVertices final : Op { 486 static const auto kType = Type::DrawVertices; 487 DrawVertices(SkCanvas::VertexMode mode, int count, SkXfermode* xfermode, int nindices, 488 const SkPaint& paint, bool has_texs, bool has_colors, bool has_indices) 489 : mode(mode), count(count), xfermode(sk_ref_sp(xfermode)), nindices(nindices) 490 , paint(paint), has_texs(has_texs), has_colors(has_colors), has_indices(has_indices) {} 491 SkCanvas::VertexMode mode; 492 int count; 493 sk_sp<SkXfermode> xfermode; 494 int nindices; 495 SkPaint paint; 496 bool has_texs; 497 bool has_colors; 498 bool has_indices; 499 void draw(SkCanvas* c, const SkMatrix&) { 500 SkPoint* vertices = pod<SkPoint>(this, 0); 501 size_t offset = count*sizeof(SkPoint); 502 503 SkPoint* texs = nullptr; 504 if (has_texs) { 505 texs = pod<SkPoint>(this, offset); 506 offset += count*sizeof(SkPoint); 507 } 508 509 SkColor* colors = nullptr; 510 if (has_colors) { 511 colors = pod<SkColor>(this, offset); 512 offset += count*sizeof(SkColor); 513 } 514 515 uint16_t* indices = nullptr; 516 if (has_indices) { 517 indices = pod<uint16_t>(this, offset); 518 } 519 c->drawVertices(mode, count, vertices, texs, colors, xfermode.get(), 520 indices, nindices, paint); 521 } 522 }; 523 struct DrawAtlas final : Op { 524 static const auto kType = Type::DrawAtlas; 525 DrawAtlas(const SkImage* atlas, int count, SkXfermode::Mode xfermode, 526 const SkRect* cull, const SkPaint* paint, bool has_colors) 527 : atlas(sk_ref_sp(atlas)), count(count), xfermode(xfermode), has_colors(has_colors) { 528 if (cull) { this->cull = *cull; } 529 if (paint) { this->paint = *paint; } 530 } 531 sk_sp<const SkImage> atlas; 532 int count; 533 SkXfermode::Mode xfermode; 534 SkRect cull = kUnset; 535 SkPaint paint; 536 bool has_colors; 537 void draw(SkCanvas* c, const SkMatrix&) { 538 auto xforms = pod<SkRSXform>(this, 0); 539 auto texs = pod<SkRect>(this, count*sizeof(SkRSXform)); 540 auto colors = has_colors 541 ? pod<SkColor>(this, count*(sizeof(SkRSXform) + sizeof(SkRect))) 542 : nullptr; 543 c->drawAtlas(atlas.get(), xforms, texs, colors, count, xfermode, 544 maybe_unset(cull), &paint); 545 } 546 }; 547} 548 549template <typename T, typename... Args> 550void* SkLiteDL::push(size_t pod, Args&&... args) { 551 size_t skip = SkAlignPtr(sizeof(T) + pod); 552 SkASSERT(skip < (1<<24)); 553 if (fUsed + skip > fReserved) { 554 static_assert(SkIsPow2(SKLITEDL_PAGE), "This math needs updating for non-pow2."); 555 // Next greater multiple of SKLITEDL_PAGE. 556 fReserved = (fUsed + skip + SKLITEDL_PAGE) & ~(SKLITEDL_PAGE-1); 557 fBytes.realloc(fReserved); 558 } 559 SkASSERT(fUsed + skip <= fReserved); 560 auto op = (T*)(fBytes.get() + fUsed); 561 fUsed += skip; 562 new (op) T{ std::forward<Args>(args)... }; 563 op->type = (uint32_t)T::kType; 564 op->skip = skip; 565 return op+1; 566} 567 568template <typename Fn, typename... Args> 569inline void SkLiteDL::map(const Fn fns[], Args... args) { 570 auto end = fBytes.get() + fUsed; 571 for (uint8_t* ptr = fBytes.get(); ptr < end; ) { 572 auto op = (Op*)ptr; 573 auto type = op->type; 574 auto skip = op->skip; 575 if (auto fn = fns[type]) { // We replace no-op functions with nullptrs 576 fn(op, args...); // to avoid the overhead of a pointless call. 577 } 578 ptr += skip; 579 } 580} 581 582#ifdef SK_SUPPORT_LEGACY_DRAWFILTER 583void SkLiteDL::setDrawFilter(SkDrawFilter* df) { 584 this->push<SetDrawFilter>(0, df); 585} 586#endif 587 588void SkLiteDL:: save() { this->push <Save>(0); } 589void SkLiteDL::restore() { this->push<Restore>(0); } 590void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint, 591 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) { 592 this->push<SaveLayer>(0, bounds, paint, backdrop, flags); 593} 594 595void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); } 596void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); } 597void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); } 598void SkLiteDL::translateZ(SkScalar dz) { this->push<TranslateZ>(0, dz); } 599 600void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) { 601 this->push<ClipPath>(0, path, op, aa); 602} 603void SkLiteDL::clipRect(const SkRect& rect, SkRegion::Op op, bool aa) { 604 this->push<ClipRect>(0, rect, op, aa); 605} 606void SkLiteDL::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool aa) { 607 this->push<ClipRRect>(0, rrect, op, aa); 608} 609void SkLiteDL::clipRegion(const SkRegion& region, SkRegion::Op op) { 610 this->push<ClipRegion>(0, region, op); 611} 612 613void SkLiteDL::drawPaint(const SkPaint& paint) { 614 this->push<DrawPaint>(0, paint); 615} 616void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) { 617 this->push<DrawPath>(0, path, paint); 618} 619void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) { 620 this->push<DrawRect>(0, rect, paint); 621} 622void SkLiteDL::drawRegion(const SkRegion& region, const SkPaint& paint) { 623 this->push<DrawRegion>(0, region, paint); 624} 625void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) { 626 this->push<DrawOval>(0, oval, paint); 627} 628void SkLiteDL::drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, 629 const SkPaint& paint) { 630 this->push<DrawArc>(0, oval, startAngle, sweepAngle, useCenter, paint); 631} 632void SkLiteDL::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 633 this->push<DrawRRect>(0, rrect, paint); 634} 635void SkLiteDL::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 636 this->push<DrawDRRect>(0, outer, inner, paint); 637} 638 639void SkLiteDL::drawAnnotation(const SkRect& rect, const char* key, SkData* value) { 640 size_t bytes = strlen(key)+1; 641 void* pod = this->push<DrawAnnotation>(bytes, rect, value); 642 copy_v(pod, key,bytes); 643} 644void SkLiteDL::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { 645 this->push<DrawDrawable>(0, drawable, matrix); 646} 647void SkLiteDL::drawPicture(const SkPicture* picture, 648 const SkMatrix* matrix, const SkPaint* paint) { 649 this->push<DrawPicture>(0, picture, matrix, paint); 650} 651void SkLiteDL::drawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, 652 const SkPaint* paint, const SkShadowParams& params) { 653 push<DrawShadowedPicture>(0, picture, matrix, paint, params); 654} 655 656void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) { 657 this->push<DrawImage>(0, SkImage::MakeFromBitmap(bm), x,y, paint); 658} 659void SkLiteDL::drawBitmapNine(const SkBitmap& bm, const SkIRect& center, 660 const SkRect& dst, const SkPaint* paint) { 661 this->push<DrawImageNine>(0, SkImage::MakeFromBitmap(bm), center, dst, paint); 662} 663void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst, 664 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { 665 this->push<DrawImageRect>(0, SkImage::MakeFromBitmap(bm), src, dst, paint, constraint); 666} 667void SkLiteDL::drawBitmapLattice(const SkBitmap& bm, const SkCanvas::Lattice& lattice, 668 const SkRect& dst, const SkPaint* paint) { 669 int xs = lattice.fXCount, ys = lattice.fYCount; 670 int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0; 671 size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags); 672 void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, fs, dst, 673 paint); 674 copy_v(pod, lattice.fXDivs, xs, 675 lattice.fYDivs, ys, 676 lattice.fFlags, fs); 677} 678 679void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 680 this->push<DrawImage>(0, sk_ref_sp(image), x,y, paint); 681} 682void SkLiteDL::drawImageNine(const SkImage* image, const SkIRect& center, 683 const SkRect& dst, const SkPaint* paint) { 684 this->push<DrawImageNine>(0, sk_ref_sp(image), center, dst, paint); 685} 686void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 687 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) { 688 this->push<DrawImageRect>(0, sk_ref_sp(image), src, dst, paint, constraint); 689} 690void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice, 691 const SkRect& dst, const SkPaint* paint) { 692 int xs = lattice.fXCount, ys = lattice.fYCount; 693 int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0; 694 size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags); 695 void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, fs, dst, paint); 696 copy_v(pod, lattice.fXDivs, xs, 697 lattice.fYDivs, ys, 698 lattice.fFlags, fs); 699} 700 701void SkLiteDL::drawText(const void* text, size_t bytes, 702 SkScalar x, SkScalar y, const SkPaint& paint) { 703 void* pod = this->push<DrawText>(bytes, bytes, x, y, paint); 704 copy_v(pod, (const char*)text,bytes); 705} 706void SkLiteDL::drawPosText(const void* text, size_t bytes, 707 const SkPoint pos[], const SkPaint& paint) { 708 int n = paint.countText(text, bytes); 709 void* pod = this->push<DrawPosText>(n*sizeof(SkPoint)+bytes, bytes, paint, n); 710 copy_v(pod, pos,n, (const char*)text,bytes); 711} 712void SkLiteDL::drawPosTextH(const void* text, size_t bytes, 713 const SkScalar xs[], SkScalar y, const SkPaint& paint) { 714 int n = paint.countText(text, bytes); 715 void* pod = this->push<DrawPosTextH>(n*sizeof(SkScalar)+bytes, bytes, y, paint, n); 716 copy_v(pod, xs,n, (const char*)text,bytes); 717} 718void SkLiteDL::drawTextOnPath(const void* text, size_t bytes, 719 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { 720 void* pod = this->push<DrawTextOnPath>(bytes, bytes, path, matrix, paint); 721 copy_v(pod, (const char*)text,bytes); 722} 723void SkLiteDL::drawTextRSXform(const void* text, size_t bytes, 724 const SkRSXform xforms[], const SkRect* cull, const SkPaint& paint) { 725 int n = paint.countText(text, bytes); 726 void* pod = this->push<DrawTextRSXform>(bytes+n*sizeof(SkRSXform), bytes, cull, paint); 727 copy_v(pod, (const char*)text,bytes, xforms,n); 728} 729void SkLiteDL::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { 730 this->push<DrawTextBlob>(0, blob, x,y, paint); 731} 732 733void SkLiteDL::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4], 734 SkXfermode* xfermode, const SkPaint& paint) { 735 this->push<DrawPatch>(0, points, colors, texs, xfermode, paint); 736} 737void SkLiteDL::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint points[], 738 const SkPaint& paint) { 739 void* pod = this->push<DrawPoints>(count*sizeof(SkPoint), mode, count, paint); 740 copy_v(pod, points,count); 741} 742void SkLiteDL::drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[], 743 const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode, 744 const uint16_t indices[], int nindices, const SkPaint& paint) { 745 size_t bytes = count * sizeof(SkPoint); 746 if (texs ) { bytes += count * sizeof(SkPoint); } 747 if (colors) { bytes += count * sizeof(SkColor); } 748 if (indices) { bytes += nindices * sizeof(uint16_t); } 749 void* pod = this->push<DrawVertices>(bytes, mode, count, xfermode, nindices, paint, 750 texs != nullptr, colors != nullptr, indices != nullptr); 751 copy_v(pod, vertices, count, 752 texs, texs ? count : 0, 753 colors, colors ? count : 0, 754 indices, indices ? nindices : 0); 755} 756void SkLiteDL::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[], 757 const SkColor colors[], int count, SkXfermode::Mode xfermode, 758 const SkRect* cull, const SkPaint* paint) { 759 size_t bytes = count*(sizeof(SkRSXform) + sizeof(SkRect)); 760 if (colors) { 761 bytes += count*sizeof(SkColor); 762 } 763 void* pod = this->push<DrawAtlas>(bytes, 764 atlas, count, xfermode, cull, paint, colors != nullptr); 765 copy_v(pod, xforms, count, 766 texs, count, 767 colors, colors ? count : 0); 768} 769 770typedef void(*draw_fn)(void*, SkCanvas*, const SkMatrix&); 771typedef void(*void_fn)(void*); 772 773// All ops implement draw(). 774#define M(T) [](void* op, SkCanvas* c, const SkMatrix& original) { ((T*)op)->draw(c, original); }, 775static const draw_fn draw_fns[] = { TYPES(M) }; 776#undef M 777 778#define M(T) [](void* op) { ((T*)op)->makeThreadsafe(); }, 779static const void_fn make_threadsafe_fns[] = { TYPES(M) }; 780#undef M 781 782// Older libstdc++ has pre-standard std::has_trivial_destructor. 783#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000) 784 template <typename T> using can_skip_destructor = std::has_trivial_destructor<T>; 785#else 786 template <typename T> using can_skip_destructor = std::is_trivially_destructible<T>; 787#endif 788 789// Most state ops (matrix, clip, save, restore) have a trivial destructor. 790#define M(T) !can_skip_destructor<T>::value ? [](void* op) { ((T*)op)->~T(); } : (void_fn)nullptr, 791static const void_fn dtor_fns[] = { TYPES(M) }; 792#undef M 793 794void SkLiteDL::onDraw(SkCanvas* canvas) { this->map(draw_fns, canvas, canvas->getTotalMatrix()); } 795void SkLiteDL::makeThreadsafe() { this->map(make_threadsafe_fns); } 796 797SkRect SkLiteDL::onGetBounds() { 798 return fBounds; 799} 800 801SkLiteDL:: SkLiteDL(SkRect bounds) : fUsed(0), fReserved(0), fBounds(bounds) {} 802 803SkLiteDL::~SkLiteDL() { 804 this->reset(SkRect::MakeEmpty()); 805} 806 807sk_sp<SkLiteDL> SkLiteDL::New(SkRect bounds) { 808 return sk_sp<SkLiteDL>(new SkLiteDL(bounds)); 809} 810 811void SkLiteDL::reset(SkRect bounds) { 812 SkASSERT(this->unique()); 813 this->map(dtor_fns); 814 815 // Leave fBytes and fReserved alone. 816 fUsed = 0; 817 fBounds = bounds; 818} 819