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" |
10 | 11 |
11 void SkRecordDraw(const SkRecord& record, | 12 void SkRecordDraw(const SkRecord& record, |
12 SkCanvas* canvas, | 13 SkCanvas* canvas, |
13 const SkBBoxHierarchy* bbh, | 14 const SkBBoxHierarchy* bbh, |
14 SkDrawPictureCallback* callback) { | 15 SkDrawPictureCallback* callback) { |
15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); | 16 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); |
16 | 17 |
17 if (bbh) { | 18 if (bbh) { |
18 // Draw only ops that affect pixels in the canvas's current clip. | 19 // Draw only ops that affect pixels in the canvas's current clip. |
19 // The SkRecord and BBH were recorded in identity space. This canvas | 20 // The SkRecord and BBH were recorded in identity space. This canvas |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 struct SaveBounds { | 178 struct SaveBounds { |
178 int controlOps; // Number of control ops in this Save block, incl
uding the Save. | 179 int controlOps; // Number of control ops in this Save block, incl
uding the Save. |
179 Bounds bounds; // Bounds of everything in the block. | 180 Bounds bounds; // Bounds of everything in the block. |
180 const SkPaint* paint; // Unowned. If set, adjusts the bounds of all op
s in this block. | 181 const SkPaint* paint; // Unowned. If set, adjusts the bounds of all op
s in this block. |
181 }; | 182 }; |
182 | 183 |
183 template <typename T> void updateCTM(const T&) { /* most ops don't change th
e CTM */ } | 184 template <typename T> void updateCTM(const T&) { /* most ops don't change th
e CTM */ } |
184 void updateCTM(const Restore& op) { fCTM = &op.matrix; } | 185 void updateCTM(const Restore& op) { fCTM = &op.matrix; } |
185 void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } | 186 void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } |
186 | 187 |
187 template <typename T> void updateClipBounds(const T&) { /* most ops don't ch
ange the clip */ } | 188 // Most ops don't change the clip. Those that do generally have a field nam
ed devBounds. |
188 // Each of these devBounds fields is the state of the device bounds after th
e op. | 189 SK_CREATE_MEMBER_DETECTOR(devBounds); |
189 // So Restore's devBounds are those bounds saved by its paired Save or SaveL
ayer. | 190 |
190 void updateClipBounds(const Restore& op) { fCurrentClipBounds = Bounds::M
ake(op.devBounds); } | 191 template <typename T> |
191 void updateClipBounds(const ClipPath& op) { fCurrentClipBounds = Bounds::M
ake(op.devBounds); } | 192 SK_WHEN(!HasMember_devBounds<T>, void) updateClipBounds(const T& op) {} |
192 void updateClipBounds(const ClipRRect& op) { fCurrentClipBounds = Bounds::M
ake(op.devBounds); } | 193 |
193 void updateClipBounds(const ClipRect& op) { fCurrentClipBounds = Bounds::M
ake(op.devBounds); } | 194 // Each of the devBounds fields holds the state of the device bounds after t
he op. |
194 void updateClipBounds(const ClipRegion& op) { fCurrentClipBounds = Bounds::M
ake(op.devBounds); } | 195 // (So Restore's devBounds are those bounds saved by its paired Save or Save
Layer.) |
| 196 template <typename T> |
| 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 // 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 } |
| 203 |
| 204 // We also take advantage of SaveLayer bounds when present to further cut th
e clip down. |
195 void updateClipBounds(const SaveLayer& op) { | 205 void updateClipBounds(const SaveLayer& op) { |
196 if (op.bounds) { | 206 if (op.bounds) { |
197 fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint
)); | 207 // adjustAndMap() intersects these layer bounds with the previous cl
ip for us. |
| 208 fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); |
198 } | 209 } |
199 } | 210 } |
200 | 211 |
201 // The bounds of these ops must be calculated when we hit the Restore | 212 // The bounds of these ops must be calculated when we hit the Restore |
202 // from the bounds of the ops in the same Save block. | 213 // from the bounds of the ops in the same Save block. |
203 void trackBounds(const Save&) { this->pushSaveBlock(NULL); } | 214 void trackBounds(const Save&) { this->pushSaveBlock(NULL); } |
204 void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } | 215 void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } |
205 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(
); } | 216 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(
); } |
206 | 217 |
207 void trackBounds(const SetMatrix&) { this->pushControl(); } | 218 void trackBounds(const SetMatrix&) { this->pushControl(); } |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 if (paint) { | 471 if (paint) { |
461 if (paint->canComputeFastBounds()) { | 472 if (paint->canComputeFastBounds()) { |
462 *rect = paint->computeFastBounds(*rect, rect); | 473 *rect = paint->computeFastBounds(*rect, rect); |
463 return true; | 474 return true; |
464 } | 475 } |
465 return false; | 476 return false; |
466 } | 477 } |
467 return true; | 478 return true; |
468 } | 479 } |
469 | 480 |
| 481 bool adjustForSaveLayerPaints(SkRect* rect) const { |
| 482 for (int i = fSaveStack.count() - 1; i >= 0; i--) { |
| 483 if (!AdjustForPaint(fSaveStack[i].paint, rect)) { |
| 484 return false; |
| 485 } |
| 486 } |
| 487 return true; |
| 488 } |
| 489 |
470 // Adjust rect for all paints that may affect its geometry, then map it to i
dentity space. | 490 // Adjust rect for all paints that may affect its geometry, then map it to i
dentity space. |
471 Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { | 491 Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { |
472 // Inverted rectangles really confuse our BBHs. | 492 // Inverted rectangles really confuse our BBHs. |
473 rect.sort(); | 493 rect.sort(); |
474 | 494 |
475 // Adjust the rect for its own paint. | 495 // Adjust the rect for its own paint. |
476 if (!AdjustForPaint(paint, &rect)) { | 496 if (!AdjustForPaint(paint, &rect)) { |
477 // The paint could do anything to our bounds. The only safe answer
is the current clip. | 497 // The paint could do anything to our bounds. The only safe answer
is the current clip. |
478 return fCurrentClipBounds; | 498 return fCurrentClipBounds; |
479 } | 499 } |
480 | 500 |
481 // Adjust rect for all the paints from the SaveLayers we're inside. | 501 // Adjust rect for all the paints from the SaveLayers we're inside. |
482 for (int i = fSaveStack.count() - 1; i >= 0; i--) { | 502 if (!this->adjustForSaveLayerPaints(&rect)) { |
483 if (!AdjustForPaint(fSaveStack[i].paint, &rect)) { | 503 // Same deal as above. |
484 // Same deal as above. | 504 return fCurrentClipBounds; |
485 return fCurrentClipBounds; | |
486 } | |
487 } | 505 } |
488 | 506 |
489 // Map the rect back to identity space. | 507 // Map the rect back to identity space. |
490 fCTM->mapRect(&rect); | 508 fCTM->mapRect(&rect); |
491 | 509 |
492 // Nothing can draw outside the current clip. | 510 // Nothing can draw outside the current clip. |
493 // (Only bounded ops call into this method, so oddballs like Clear don't
matter here.) | 511 // (Only bounded ops call into this method, so oddballs like Clear don't
matter here.) |
494 rect.intersect(fCurrentClipBounds); | 512 rect.intersect(fCurrentClipBounds); |
495 return rect; | 513 return rect; |
496 } | 514 } |
(...skipping 11 matching lines...) Expand all Loading... |
508 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. | 526 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. |
509 SkTDArray<SaveBounds> fSaveStack; | 527 SkTDArray<SaveBounds> fSaveStack; |
510 SkTDArray<unsigned> fControlIndices; | 528 SkTDArray<unsigned> fControlIndices; |
511 }; | 529 }; |
512 | 530 |
513 } // namespace SkRecords | 531 } // namespace SkRecords |
514 | 532 |
515 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 533 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
516 SkRecords::FillBounds(record, bbh); | 534 SkRecords::FillBounds(record, bbh); |
517 } | 535 } |
OLD | NEW |