| 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 |