OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkLayerInfo.h" | 8 #include "SkLayerInfo.h" |
9 #include "SkRecordDraw.h" | 9 #include "SkRecordDraw.h" |
10 #include "SkPatchUtils.h" | 10 #include "SkPatchUtils.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 } | 57 } |
58 } | 58 } |
59 | 59 |
60 void SkRecordPartialDraw(const SkRecord& record, SkCanvas* canvas, | 60 void SkRecordPartialDraw(const SkRecord& record, SkCanvas* canvas, |
61 SkPicture const* const drawablePicts[], int drawableCou
nt, | 61 SkPicture const* const drawablePicts[], int drawableCou
nt, |
62 int start, int stop, | 62 int start, int stop, |
63 const SkMatrix& initialCTM) { | 63 const SkMatrix& initialCTM) { |
64 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); | 64 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); |
65 | 65 |
66 stop = SkTMin(stop, record.count()); | 66 stop = SkTMin(stop, record.count()); |
67 SkRecords::Draw draw(canvas, drawablePicts, NULL, drawableCount, &initialCTM
); | 67 SkRecords::Draw draw(canvas, drawablePicts, nullptr, drawableCount, &initial
CTM); |
68 for (int i = start; i < stop; i++) { | 68 for (int i = start; i < stop; i++) { |
69 record.visit<void>(i, draw); | 69 record.visit<void>(i, draw); |
70 } | 70 } |
71 } | 71 } |
72 | 72 |
73 namespace SkRecords { | 73 namespace SkRecords { |
74 | 74 |
75 // NoOps draw nothing. | 75 // NoOps draw nothing. |
76 template <> void Draw::draw(const NoOp&) {} | 76 template <> void Draw::draw(const NoOp&) {} |
77 | 77 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.p
aint)); | 116 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.p
aint)); |
117 DRAW(DrawAtlas, drawAtlas(r.atlas, r.xforms, r.texs, r.colors, r.count, r.mode,
r.cull, r.paint)); | 117 DRAW(DrawAtlas, drawAtlas(r.atlas, r.xforms, r.texs, r.colors, r.count, r.mode,
r.cull, r.paint)); |
118 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co
lors, | 118 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co
lors, |
119 r.xmode.get(), r.indices, r.indexCount, r.paint)
); | 119 r.xmode.get(), r.indices, r.indexCount, r.paint)
); |
120 #undef DRAW | 120 #undef DRAW |
121 | 121 |
122 template <> void Draw::draw(const DrawDrawable& r) { | 122 template <> void Draw::draw(const DrawDrawable& r) { |
123 SkASSERT(r.index >= 0); | 123 SkASSERT(r.index >= 0); |
124 SkASSERT(r.index < fDrawableCount); | 124 SkASSERT(r.index < fDrawableCount); |
125 if (fDrawables) { | 125 if (fDrawables) { |
126 SkASSERT(NULL == fDrawablePicts); | 126 SkASSERT(nullptr == fDrawablePicts); |
127 fCanvas->drawDrawable(fDrawables[r.index], r.matrix); | 127 fCanvas->drawDrawable(fDrawables[r.index], r.matrix); |
128 } else { | 128 } else { |
129 fCanvas->drawPicture(fDrawablePicts[r.index], r.matrix, NULL); | 129 fCanvas->drawPicture(fDrawablePicts[r.index], r.matrix, nullptr); |
130 } | 130 } |
131 } | 131 } |
132 | 132 |
133 // This is an SkRecord visitor that fills an SkBBoxHierarchy. | 133 // This is an SkRecord visitor that fills an SkBBoxHierarchy. |
134 // | 134 // |
135 // The interesting part here is how to calculate bounds for ops which don't | 135 // The interesting part here is how to calculate bounds for ops which don't |
136 // have intrinsic bounds. What is the bounds of a Save or a Translate? | 136 // have intrinsic bounds. What is the bounds of a Save or a Translate? |
137 // | 137 // |
138 // We answer this by thinking about a particular definition of bounds: if I | 138 // We answer this by thinking about a particular definition of bounds: if I |
139 // don't execute this op, pixels in this rectangle might draw incorrectly. So | 139 // don't execute this op, pixels in this rectangle might draw incorrectly. So |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 // We also take advantage of SaveLayer bounds when present to further cut th
e clip down. | 273 // We also take advantage of SaveLayer bounds when present to further cut th
e clip down. |
274 void updateClipBounds(const SaveLayer& op) { | 274 void updateClipBounds(const SaveLayer& op) { |
275 if (op.bounds) { | 275 if (op.bounds) { |
276 // adjustAndMap() intersects these layer bounds with the previous cl
ip for us. | 276 // adjustAndMap() intersects these layer bounds with the previous cl
ip for us. |
277 fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); | 277 fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); |
278 } | 278 } |
279 } | 279 } |
280 | 280 |
281 // The bounds of these ops must be calculated when we hit the Restore | 281 // The bounds of these ops must be calculated when we hit the Restore |
282 // from the bounds of the ops in the same Save block. | 282 // from the bounds of the ops in the same Save block. |
283 void trackBounds(const Save&) { this->pushSaveBlock(NULL); } | 283 void trackBounds(const Save&) { this->pushSaveBlock(nullptr); } |
284 void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } | 284 void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } |
285 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(
); } | 285 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(
); } |
286 | 286 |
287 void trackBounds(const SetMatrix&) { this->pushControl(); } | 287 void trackBounds(const SetMatrix&) { this->pushControl(); } |
288 void trackBounds(const ClipRect&) { this->pushControl(); } | 288 void trackBounds(const ClipRect&) { this->pushControl(); } |
289 void trackBounds(const ClipRRect&) { this->pushControl(); } | 289 void trackBounds(const ClipRRect&) { this->pushControl(); } |
290 void trackBounds(const ClipPath&) { this->pushControl(); } | 290 void trackBounds(const ClipPath&) { this->pushControl(); } |
291 void trackBounds(const ClipRegion&) { this->pushControl(); } | 291 void trackBounds(const ClipRegion&) { this->pushControl(); } |
292 | 292 |
293 // For all other ops, we can calculate and store the bounds directly now. | 293 // For all other ops, we can calculate and store the bounds directly now. |
(...skipping 23 matching lines...) Expand all Loading... |
317 return true; | 317 return true; |
318 } | 318 } |
319 | 319 |
320 // Unusual Xfermodes require us to process a saved layer | 320 // Unusual Xfermodes require us to process a saved layer |
321 // even with operations outisde the clip. | 321 // even with operations outisde the clip. |
322 // For example, DstIn is used by masking layers. | 322 // For example, DstIn is used by masking layers. |
323 // https://code.google.com/p/skia/issues/detail?id=1291 | 323 // https://code.google.com/p/skia/issues/detail?id=1291 |
324 // https://crbug.com/401593 | 324 // https://crbug.com/401593 |
325 SkXfermode* xfermode = paint->getXfermode(); | 325 SkXfermode* xfermode = paint->getXfermode(); |
326 SkXfermode::Mode mode; | 326 SkXfermode::Mode mode; |
327 // SrcOver is ok, and is also the common case with a NULL xfermode. | 327 // SrcOver is ok, and is also the common case with a nullptr xfermod
e. |
328 // So we should make that the fast path and bypass the mode extracti
on | 328 // So we should make that the fast path and bypass the mode extracti
on |
329 // and test. | 329 // and test. |
330 if (xfermode && xfermode->asMode(&mode)) { | 330 if (xfermode && xfermode->asMode(&mode)) { |
331 switch (mode) { | 331 switch (mode) { |
332 // For each of the following transfer modes, if the source | 332 // For each of the following transfer modes, if the source |
333 // alpha is zero (our transparent black), the resulting | 333 // alpha is zero (our transparent black), the resulting |
334 // blended alpha is not necessarily equal to the original | 334 // blended alpha is not necessarily equal to the original |
335 // destination alpha. | 335 // destination alpha. |
336 case SkXfermode::kClear_Mode: | 336 case SkXfermode::kClear_Mode: |
337 case SkXfermode::kSrc_Mode: | 337 case SkXfermode::kSrc_Mode: |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 return this->adjustAndMap(dst, &op.paint); | 518 return this->adjustAndMap(dst, &op.paint); |
519 } | 519 } |
520 | 520 |
521 Bounds bounds(const DrawTextBlob& op) const { | 521 Bounds bounds(const DrawTextBlob& op) const { |
522 SkRect dst = op.blob->bounds(); | 522 SkRect dst = op.blob->bounds(); |
523 dst.offset(op.x, op.y); | 523 dst.offset(op.x, op.y); |
524 return this->adjustAndMap(dst, &op.paint); | 524 return this->adjustAndMap(dst, &op.paint); |
525 } | 525 } |
526 | 526 |
527 Bounds bounds(const DrawDrawable& op) const { | 527 Bounds bounds(const DrawDrawable& op) const { |
528 return this->adjustAndMap(op.worstCaseBounds, NULL); | 528 return this->adjustAndMap(op.worstCaseBounds, nullptr); |
529 } | 529 } |
530 | 530 |
531 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { | 531 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { |
532 #ifdef SK_DEBUG | 532 #ifdef SK_DEBUG |
533 SkRect correct = *rect; | 533 SkRect correct = *rect; |
534 #endif | 534 #endif |
535 // crbug.com/373785 ~~> xPad = 4x yPad | 535 // crbug.com/373785 ~~> xPad = 4x yPad |
536 // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x | 536 // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x |
537 const SkScalar yPad = 2.5f * paint.getTextSize(), | 537 const SkScalar yPad = 2.5f * paint.getTextSize(), |
538 xPad = 4.0f * yPad; | 538 xPad = 4.0f * yPad; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 int fStartIndex; | 637 int fStartIndex; |
638 bool fIsSaveLayer; | 638 bool fIsSaveLayer; |
639 bool fHasNestedSaveLayer; | 639 bool fHasNestedSaveLayer; |
640 SkRect fBounds; | 640 SkRect fBounds; |
641 const SkPaint* fPaint; | 641 const SkPaint* fPaint; |
642 }; | 642 }; |
643 | 643 |
644 template <typename T> void trackSaveLayers(const T& op) { | 644 template <typename T> void trackSaveLayers(const T& op) { |
645 /* most ops aren't involved in saveLayers */ | 645 /* most ops aren't involved in saveLayers */ |
646 } | 646 } |
647 void trackSaveLayers(const Save& s) { this->pushSaveLayerInfo(false, NULL, N
ULL); } | 647 void trackSaveLayers(const Save& s) { this->pushSaveLayerInfo(false, nullptr
, nullptr); } |
648 void trackSaveLayers(const SaveLayer& sl) { this->pushSaveLayerInfo(true, sl
.bounds, sl.paint); } | 648 void trackSaveLayers(const SaveLayer& sl) { this->pushSaveLayerInfo(true, sl
.bounds, sl.paint); } |
649 void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); } | 649 void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); } |
650 | 650 |
651 void trackSaveLayersForPicture(const SkPicture* picture, const SkPaint* pain
t) { | 651 void trackSaveLayersForPicture(const SkPicture* picture, const SkPaint* pain
t) { |
652 // For sub-pictures, we wrap their layer information within the parent | 652 // For sub-pictures, we wrap their layer information within the parent |
653 // picture's rendering hierarchy | 653 // picture's rendering hierarchy |
654 const SkLayerInfo* childData = NULL; | 654 const SkLayerInfo* childData = nullptr; |
655 if (const SkBigPicture* bp = picture->asSkBigPicture()) { | 655 if (const SkBigPicture* bp = picture->asSkBigPicture()) { |
656 childData = static_cast<const SkLayerInfo*>(bp->accelData()); | 656 childData = static_cast<const SkLayerInfo*>(bp->accelData()); |
657 } | 657 } |
658 if (!childData) { | 658 if (!childData) { |
659 // If the child layer hasn't been generated with saveLayer data we | 659 // If the child layer hasn't been generated with saveLayer data we |
660 // assume the worst (i.e., that it does contain layers which nest | 660 // assume the worst (i.e., that it does contain layers which nest |
661 // inside existing layers). Layers within sub-pictures that don't | 661 // inside existing layers). Layers within sub-pictures that don't |
662 // have saveLayer data cannot be hoisted. | 662 // have saveLayer data cannot be hoisted. |
663 // TODO: could the analysis data be use to fine tune this? | 663 // TODO: could the analysis data be use to fine tune this? |
664 this->updateStackForSaveLayer(); | 664 this->updateStackForSaveLayer(); |
665 return; | 665 return; |
666 } | 666 } |
667 | 667 |
668 for (int i = 0; i < childData->numBlocks(); ++i) { | 668 for (int i = 0; i < childData->numBlocks(); ++i) { |
669 const SkLayerInfo::BlockInfo& src = childData->block(i); | 669 const SkLayerInfo::BlockInfo& src = childData->block(i); |
670 | 670 |
671 FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds,
paint); | 671 FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds,
paint); |
672 if (newBound.isEmpty()) { | 672 if (newBound.isEmpty()) { |
673 continue; | 673 continue; |
674 } | 674 } |
675 | 675 |
676 this->updateStackForSaveLayer(); | 676 this->updateStackForSaveLayer(); |
677 | 677 |
678 SkLayerInfo::BlockInfo& dst = fAccelData->addBlock(); | 678 SkLayerInfo::BlockInfo& dst = fAccelData->addBlock(); |
679 | 679 |
680 // If src.fPicture is NULL the layer is in dp.picture; otherwise | 680 // If src.fPicture is nullptr the layer is in dp.picture; otherwise |
681 // it belongs to a sub-picture. | 681 // it belongs to a sub-picture. |
682 dst.fPicture = src.fPicture ? src.fPicture : picture; | 682 dst.fPicture = src.fPicture ? src.fPicture : picture; |
683 dst.fPicture->ref(); | 683 dst.fPicture->ref(); |
684 dst.fBounds = newBound; | 684 dst.fBounds = newBound; |
685 dst.fSrcBounds = src.fSrcBounds; | 685 dst.fSrcBounds = src.fSrcBounds; |
686 dst.fLocalMat = src.fLocalMat; | 686 dst.fLocalMat = src.fLocalMat; |
687 dst.fPreMat = src.fPreMat; | 687 dst.fPreMat = src.fPreMat; |
688 dst.fPreMat.postConcat(fFillBounds.ctm()); | 688 dst.fPreMat.postConcat(fFillBounds.ctm()); |
689 if (src.fPaint) { | 689 if (src.fPaint) { |
690 dst.fPaint = new SkPaint(*src.fPaint); | 690 dst.fPaint = new SkPaint(*src.fPaint); |
(...skipping 12 matching lines...) Expand all Loading... |
703 } | 703 } |
704 } | 704 } |
705 | 705 |
706 void trackSaveLayers(const DrawPicture& dp) { | 706 void trackSaveLayers(const DrawPicture& dp) { |
707 this->trackSaveLayersForPicture(dp.picture, dp.paint); | 707 this->trackSaveLayersForPicture(dp.picture, dp.paint); |
708 } | 708 } |
709 | 709 |
710 void trackSaveLayers(const DrawDrawable& dp) { | 710 void trackSaveLayers(const DrawDrawable& dp) { |
711 SkASSERT(fPictList); | 711 SkASSERT(fPictList); |
712 SkASSERT(dp.index >= 0 && dp.index < fPictList->count()); | 712 SkASSERT(dp.index >= 0 && dp.index < fPictList->count()); |
713 const SkPaint* paint = NULL; // drawables don't get a side-car paint | 713 const SkPaint* paint = nullptr; // drawables don't get a side-car pai
nt |
714 this->trackSaveLayersForPicture(fPictList->begin()[dp.index], paint); | 714 this->trackSaveLayersForPicture(fPictList->begin()[dp.index], paint); |
715 } | 715 } |
716 | 716 |
717 // Inform all the saveLayers already on the stack that they now have a | 717 // Inform all the saveLayers already on the stack that they now have a |
718 // nested saveLayer inside them | 718 // nested saveLayer inside them |
719 void updateStackForSaveLayer() { | 719 void updateStackForSaveLayer() { |
720 for (int index = fSaveLayerStack.count() - 1; index >= 0; --index) { | 720 for (int index = fSaveLayerStack.count() - 1; index >= 0; --index) { |
721 if (fSaveLayerStack[index].fHasNestedSaveLayer) { | 721 if (fSaveLayerStack[index].fHasNestedSaveLayer) { |
722 break; | 722 break; |
723 } | 723 } |
(...skipping 26 matching lines...) Expand all Loading... |
750 fSaveLayerStack.pop(&sli); | 750 fSaveLayerStack.pop(&sli); |
751 | 751 |
752 if (!sli.fIsSaveLayer) { | 752 if (!sli.fIsSaveLayer) { |
753 return; | 753 return; |
754 } | 754 } |
755 | 755 |
756 --fSaveLayersInStack; | 756 --fSaveLayersInStack; |
757 | 757 |
758 SkLayerInfo::BlockInfo& block = fAccelData->addBlock(); | 758 SkLayerInfo::BlockInfo& block = fAccelData->addBlock(); |
759 | 759 |
760 SkASSERT(NULL == block.fPicture); // This layer is in the top-most pict
ure | 760 SkASSERT(nullptr == block.fPicture); // This layer is in the top-most p
icture |
761 | 761 |
762 block.fBounds = fFillBounds.getBounds(sli.fStartIndex); | 762 block.fBounds = fFillBounds.getBounds(sli.fStartIndex); |
763 block.fLocalMat = fFillBounds.ctm(); | 763 block.fLocalMat = fFillBounds.ctm(); |
764 block.fPreMat = SkMatrix::I(); | 764 block.fPreMat = SkMatrix::I(); |
765 if (sli.fPaint) { | 765 if (sli.fPaint) { |
766 block.fPaint = new SkPaint(*sli.fPaint); | 766 block.fPaint = new SkPaint(*sli.fPaint); |
767 } | 767 } |
768 | 768 |
769 block.fSrcBounds = sli.fBounds; | 769 block.fSrcBounds = sli.fBounds; |
770 block.fSaveLayerOpID = sli.fStartIndex; | 770 block.fSaveLayerOpID = sli.fStartIndex; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 SkRecords::CollectLayers visitor(cullRect, record, pictList, data); | 809 SkRecords::CollectLayers visitor(cullRect, record, pictList, data); |
810 | 810 |
811 for (int curOp = 0; curOp < record.count(); curOp++) { | 811 for (int curOp = 0; curOp < record.count(); curOp++) { |
812 visitor.setCurrentOp(curOp); | 812 visitor.setCurrentOp(curOp); |
813 record.visit<void>(curOp, visitor); | 813 record.visit<void>(curOp, visitor); |
814 } | 814 } |
815 | 815 |
816 visitor.cleanUp(bbh); | 816 visitor.cleanUp(bbh); |
817 } | 817 } |
818 | 818 |
OLD | NEW |