| OLD | NEW |
| (Empty) |
| 1 | |
| 2 /* | |
| 3 * Copyright 2012 Google Inc. | |
| 4 * | |
| 5 * Use of this source code is governed by a BSD-style license that can be | |
| 6 * found in the LICENSE file. | |
| 7 */ | |
| 8 | |
| 9 #include "SkBBoxHierarchyRecord.h" | |
| 10 #include "SkPictureStateTree.h" | |
| 11 | |
| 12 SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size, | |
| 13 uint32_t recordFlags, | |
| 14 SkBBoxHierarchy* h) | |
| 15 : INHERITED(size, recordFlags) { | |
| 16 fStateTree = SkNEW(SkPictureStateTree); | |
| 17 fBoundingHierarchy = h; | |
| 18 fBoundingHierarchy->ref(); | |
| 19 fBoundingHierarchy->setClient(this); | |
| 20 } | |
| 21 | |
| 22 void SkBBoxHierarchyRecord::handleBBox(const SkRect& bounds) { | |
| 23 SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().
bytesWritten()); | |
| 24 fBoundingHierarchy->insert(draw, bounds, true); | |
| 25 } | |
| 26 | |
| 27 void SkBBoxHierarchyRecord::willSave() { | |
| 28 fStateTree->appendSave(); | |
| 29 this->INHERITED::willSave(); | |
| 30 } | |
| 31 | |
| 32 SkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* b
ounds, | |
| 33 const SkPaint*
paint, | |
| 34 SaveFlags flags
) { | |
| 35 // For now, assume all filters affect transparent black. | |
| 36 // FIXME: This could be made less conservative as an optimization. | |
| 37 bool paintAffectsTransparentBlack = paint && | |
| 38 ((paint->getImageFilter()) || | |
| 39 (paint->getColorFilter())); | |
| 40 bool needToHandleBBox = paintAffectsTransparentBlack; | |
| 41 if (!needToHandleBBox && paint) { | |
| 42 // Unusual Xfermodes require us to process a saved layer | |
| 43 // even with operations outisde the clip. | |
| 44 // For example, DstIn is used by masking layers. | |
| 45 // https://code.google.com/p/skia/issues/detail?id=1291 | |
| 46 SkXfermode* xfermode = paint->getXfermode(); | |
| 47 SkXfermode::Mode mode; | |
| 48 // SrcOver is the common case with a NULL xfermode, so we should | |
| 49 // make that the fast path and bypass the mode extraction and test. | |
| 50 if (xfermode && xfermode->asMode(&mode)) { | |
| 51 switch (mode) { | |
| 52 case SkXfermode::kClear_Mode: | |
| 53 case SkXfermode::kSrc_Mode: | |
| 54 case SkXfermode::kSrcIn_Mode: | |
| 55 case SkXfermode::kDstIn_Mode: | |
| 56 case SkXfermode::kSrcOut_Mode: | |
| 57 case SkXfermode::kDstATop_Mode: | |
| 58 case SkXfermode::kModulate_Mode: | |
| 59 needToHandleBBox = true; | |
| 60 break; | |
| 61 default: | |
| 62 break; | |
| 63 } | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 SkRect drawBounds; | |
| 68 if (needToHandleBBox) { | |
| 69 SkIRect deviceBounds; | |
| 70 this->getClipDeviceBounds(&deviceBounds); | |
| 71 drawBounds.set(deviceBounds); | |
| 72 } | |
| 73 fStateTree->appendSaveLayer(this->writeStream().bytesWritten()); | |
| 74 SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds
, paint, flags); | |
| 75 if (needToHandleBBox) { | |
| 76 this->handleBBox(drawBounds); | |
| 77 this->addNoOp(); | |
| 78 } | |
| 79 return strategy; | |
| 80 } | |
| 81 | |
| 82 void SkBBoxHierarchyRecord::willRestore() { | |
| 83 fStateTree->appendRestore(); | |
| 84 this->INHERITED::willRestore(); | |
| 85 } | |
| 86 | |
| 87 void SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) { | |
| 88 fStateTree->appendTransform(getTotalMatrix()); | |
| 89 INHERITED::didConcat(matrix); | |
| 90 } | |
| 91 | |
| 92 void SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) { | |
| 93 fStateTree->appendTransform(getTotalMatrix()); | |
| 94 INHERITED::didSetMatrix(matrix); | |
| 95 } | |
| 96 | |
| 97 void SkBBoxHierarchyRecord::onClipRect(const SkRect& rect, | |
| 98 SkRegion::Op op, | |
| 99 ClipEdgeStyle edgeStyle) { | |
| 100 fStateTree->appendClip(this->writeStream().bytesWritten()); | |
| 101 this->INHERITED::onClipRect(rect, op, edgeStyle); | |
| 102 } | |
| 103 | |
| 104 void SkBBoxHierarchyRecord::onClipRegion(const SkRegion& region, | |
| 105 SkRegion::Op op) { | |
| 106 fStateTree->appendClip(this->writeStream().bytesWritten()); | |
| 107 this->INHERITED::onClipRegion(region, op); | |
| 108 } | |
| 109 | |
| 110 void SkBBoxHierarchyRecord::onClipPath(const SkPath& path, | |
| 111 SkRegion::Op op, | |
| 112 ClipEdgeStyle edgeStyle) { | |
| 113 fStateTree->appendClip(this->writeStream().bytesWritten()); | |
| 114 this->INHERITED::onClipPath(path, op, edgeStyle); | |
| 115 } | |
| 116 | |
| 117 void SkBBoxHierarchyRecord::onClipRRect(const SkRRect& rrect, | |
| 118 SkRegion::Op op, | |
| 119 ClipEdgeStyle edgeStyle) { | |
| 120 fStateTree->appendClip(this->writeStream().bytesWritten()); | |
| 121 this->INHERITED::onClipRRect(rrect, op, edgeStyle); | |
| 122 } | |
| 123 | |
| 124 bool SkBBoxHierarchyRecord::shouldRewind(void* data) { | |
| 125 // SkBBoxHierarchy::rewindInserts is called by SkPicture after the | |
| 126 // SkPicture has rewound its command stream. To match that rewind in the | |
| 127 // BBH, we rewind all draws that reference commands that were recorded | |
| 128 // past the point to which the SkPicture has rewound, which is given by | |
| 129 // writeStream().bytesWritten(). | |
| 130 SkPictureStateTree::Draw* draw = static_cast<SkPictureStateTree::Draw*>(data
); | |
| 131 return draw->fOffset >= writeStream().bytesWritten(); | |
| 132 } | |
| OLD | NEW |