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 |