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 "SkRecordDraw.h" | 8 #include "SkRecordDraw.h" |
9 #include "SkPatchUtils.h" | 9 #include "SkPatchUtils.h" |
10 #include "SkTLogic.h" | |
11 | 10 |
12 void SkRecordDraw(const SkRecord& record, | 11 void SkRecordDraw(const SkRecord& record, |
13 SkCanvas* canvas, | 12 SkCanvas* canvas, |
14 const SkBBoxHierarchy* bbh, | 13 const SkBBoxHierarchy* bbh, |
15 SkDrawPictureCallback* callback) { | 14 SkDrawPictureCallback* callback) { |
16 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); | 15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); |
17 | 16 |
18 if (bbh) { | 17 if (bbh) { |
19 // Draw only ops that affect pixels in the canvas's current clip. | 18 // Draw only ops that affect pixels in the canvas's current clip. |
20 // The SkRecord and BBH were recorded in identity space. This canvas | 19 // The SkRecord and BBH were recorded in identity space. This canvas |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 private: | 173 private: |
175 // In this file, SkRect are in local coordinates, Bounds are translated back
to identity space. | 174 // In this file, SkRect are in local coordinates, Bounds are translated back
to identity space. |
176 typedef SkRect Bounds; | 175 typedef SkRect Bounds; |
177 | 176 |
178 struct SaveBounds { | 177 struct SaveBounds { |
179 int controlOps; // Number of control ops in this Save block, incl
uding the Save. | 178 int controlOps; // Number of control ops in this Save block, incl
uding the Save. |
180 Bounds bounds; // Bounds of everything in the block. | 179 Bounds bounds; // Bounds of everything in the block. |
181 const SkPaint* paint; // Unowned. If set, adjusts the bounds of all op
s in this block. | 180 const SkPaint* paint; // Unowned. If set, adjusts the bounds of all op
s in this block. |
182 }; | 181 }; |
183 | 182 |
184 template <typename T> void updateCTM(const T&) { /* most ops don't change th
e CTM */ } | 183 // Only Restore and SetMatrix change the CTM. |
| 184 template <typename T> void updateCTM(const T&) {} |
185 void updateCTM(const Restore& op) { fCTM = &op.matrix; } | 185 void updateCTM(const Restore& op) { fCTM = &op.matrix; } |
186 void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } | 186 void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } |
187 | 187 |
188 // Most ops don't change the clip. Those that do generally have a field nam
ed devBounds. | 188 // Most ops don't change the clip. |
189 SK_CREATE_MEMBER_DETECTOR(devBounds); | 189 template <typename T> void updateClipBounds(const T&) {} |
190 | 190 |
191 template <typename T> | 191 // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know th
eir bounds already. |
192 SK_WHEN(!HasMember_devBounds<T>, void) updateClipBounds(const T& op) {} | 192 void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipO
p(op.devBounds); } |
| 193 void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipO
p(op.devBounds); } |
| 194 void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipO
p(op.devBounds); } |
| 195 void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipO
p(op.devBounds); } |
193 | 196 |
194 // Each of the devBounds fields holds the state of the device bounds after t
he op. | 197 // The bounds of clip ops need to be adjusted for the paints of saveLayers t
hey're inside. |
195 // (So Restore's devBounds are those bounds saved by its paired Save or Save
Layer.) | 198 void updateClipBoundsForClipOp(const SkIRect& devBounds) { |
196 template <typename T> | 199 Bounds clip = SkRect::Make(devBounds); |
197 SK_WHEN(HasMember_devBounds<T>, void) updateClipBounds(const T& op) { | |
198 Bounds clip = SkRect::Make(op.devBounds); | |
199 // We don't call adjustAndMap() because as its last step it would inters
ect the adjusted | 200 // We don't call adjustAndMap() because as its last step it would inters
ect the adjusted |
200 // clip bounds with the previous clip, exactly what we can't do when the
clip grows. | 201 // clip bounds with the previous clip, exactly what we can't do when the
clip grows. |
201 fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : Boun
ds::MakeLargest(); | 202 fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : Boun
ds::MakeLargest(); |
202 } | 203 } |
203 | 204 |
| 205 // Restore holds the devBounds for the clip after the {save,saveLayer}/resto
re block completes. |
| 206 void updateClipBounds(const Restore& op) { |
| 207 // This is just like the clip ops above, but we need to skip the effects
(if any) of our |
| 208 // paired saveLayer (if it is one); it has not yet been popped off the s
ave stack. Our |
| 209 // devBounds reflect the state of the world after the saveLayer/restore
block is done, |
| 210 // so they are not affected by the saveLayer's paint. |
| 211 const int kSavesToIgnore = 1; |
| 212 Bounds clip = SkRect::Make(op.devBounds); |
| 213 fCurrentClipBounds = |
| 214 this->adjustForSaveLayerPaints(&clip, kSavesToIgnore) ? clip : Bound
s::MakeLargest(); |
| 215 } |
| 216 |
204 // We also take advantage of SaveLayer bounds when present to further cut th
e clip down. | 217 // We also take advantage of SaveLayer bounds when present to further cut th
e clip down. |
205 void updateClipBounds(const SaveLayer& op) { | 218 void updateClipBounds(const SaveLayer& op) { |
206 if (op.bounds) { | 219 if (op.bounds) { |
207 // adjustAndMap() intersects these layer bounds with the previous cl
ip for us. | 220 // adjustAndMap() intersects these layer bounds with the previous cl
ip for us. |
208 fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); | 221 fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); |
209 } | 222 } |
210 } | 223 } |
211 | 224 |
212 // The bounds of these ops must be calculated when we hit the Restore | 225 // The bounds of these ops must be calculated when we hit the Restore |
213 // from the bounds of the ops in the same Save block. | 226 // from the bounds of the ops in the same Save block. |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 if (paint) { | 484 if (paint) { |
472 if (paint->canComputeFastBounds()) { | 485 if (paint->canComputeFastBounds()) { |
473 *rect = paint->computeFastBounds(*rect, rect); | 486 *rect = paint->computeFastBounds(*rect, rect); |
474 return true; | 487 return true; |
475 } | 488 } |
476 return false; | 489 return false; |
477 } | 490 } |
478 return true; | 491 return true; |
479 } | 492 } |
480 | 493 |
481 bool adjustForSaveLayerPaints(SkRect* rect) const { | 494 bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const { |
482 for (int i = fSaveStack.count() - 1; i >= 0; i--) { | 495 for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) { |
483 if (!AdjustForPaint(fSaveStack[i].paint, rect)) { | 496 if (!AdjustForPaint(fSaveStack[i].paint, rect)) { |
484 return false; | 497 return false; |
485 } | 498 } |
486 } | 499 } |
487 return true; | 500 return true; |
488 } | 501 } |
489 | 502 |
490 // Adjust rect for all paints that may affect its geometry, then map it to i
dentity space. | 503 // Adjust rect for all paints that may affect its geometry, then map it to i
dentity space. |
491 Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { | 504 Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { |
492 // Inverted rectangles really confuse our BBHs. | 505 // Inverted rectangles really confuse our BBHs. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. | 539 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. |
527 SkTDArray<SaveBounds> fSaveStack; | 540 SkTDArray<SaveBounds> fSaveStack; |
528 SkTDArray<unsigned> fControlIndices; | 541 SkTDArray<unsigned> fControlIndices; |
529 }; | 542 }; |
530 | 543 |
531 } // namespace SkRecords | 544 } // namespace SkRecords |
532 | 545 |
533 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 546 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
534 SkRecords::FillBounds(record, bbh); | 547 SkRecords::FillBounds(record, bbh); |
535 } | 548 } |
OLD | NEW |