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