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