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 "SkTSort.h" | 9 #include "SkTSort.h" |
10 | 10 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 } | 232 } |
233 | 233 |
234 void updateSaveBounds(const SkIRect& bounds) { | 234 void updateSaveBounds(const SkIRect& bounds) { |
235 // If we're in a Save block, expand its bounds to cover these bounds too
. | 235 // If we're in a Save block, expand its bounds to cover these bounds too
. |
236 if (!fSaveStack.isEmpty()) { | 236 if (!fSaveStack.isEmpty()) { |
237 fSaveStack.top().bounds.join(bounds); | 237 fSaveStack.top().bounds.join(bounds); |
238 } | 238 } |
239 } | 239 } |
240 | 240 |
241 // TODO: Remove this default when done bounding all ops. | 241 // TODO: Remove this default when done bounding all ops. |
242 template <typename T> SkIRect bounds(const T&) { return fCurrentClipBounds;
} | 242 template <typename T> SkIRect bounds(const T&) const { return fCurrentClipBo
unds; } |
243 SkIRect bounds(const Clear&) { return SkIRect::MakeLargest(); } // Ignores
the clip | 243 SkIRect bounds(const Clear&) const { return SkIRect::MakeLargest(); } // Ig
nores the clip |
244 SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); } // NoOps do
n't draw anywhere. | 244 SkIRect bounds(const NoOp&) const { return SkIRect::MakeEmpty(); } // No
Ops don't draw. |
| 245 |
| 246 // Returns true if rect was meaningfully adjusted for the effects of paint, |
| 247 // false if the paint could affect the rect in unknown ways. |
| 248 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { |
| 249 if (paint) { |
| 250 if (paint->canComputeFastBounds()) { |
| 251 *rect = paint->computeFastBounds(*rect, rect); |
| 252 return true; |
| 253 } |
| 254 return false; |
| 255 } |
| 256 return true; |
| 257 } |
245 | 258 |
246 // Adjust rect for all paints that may affect its geometry, then map it to d
evice space. | 259 // Adjust rect for all paints that may affect its geometry, then map it to d
evice space. |
247 SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) { | 260 SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) const { |
248 // Adjust rect for its own paint. | 261 // Inverted rectangles really confuse our BBHs. |
249 if (paint) { | 262 rect.sort(); |
250 if (paint->canComputeFastBounds()) { | 263 |
251 rect = paint->computeFastBounds(rect, &rect); | 264 // Adjust the rect for its own paint. |
252 } else { | 265 if (!AdjustForPaint(paint, &rect)) { |
253 // The paint could do anything. The only safe answer is the cur
rent clip. | 266 // The paint could do anything to our bounds. The only safe answer
is the current clip. |
| 267 return fCurrentClipBounds; |
| 268 } |
| 269 |
| 270 // Adjust rect for all the paints from the SaveLayers we're inside. |
| 271 for (int i = fSaveStack.count() - 1; i >= 0; i--) { |
| 272 if (!AdjustForPaint(fSaveStack[i].paint, &rect)) { |
| 273 // Same deal as above. |
254 return fCurrentClipBounds; | 274 return fCurrentClipBounds; |
255 } | 275 } |
256 } | 276 } |
257 | 277 |
258 // Adjust rect for all the paints from the SaveLayers we're inside. | |
259 // For SaveLayers, only image filters will affect the bounds. | |
260 for (int i = fSaveStack.count() - 1; i >= 0; i--) { | |
261 if (fSaveStack[i].paint && fSaveStack[i].paint->getImageFilter()) { | |
262 if (paint->canComputeFastBounds()) { | |
263 rect = fSaveStack[i].paint->computeFastBounds(rect, &rect); | |
264 } else { | |
265 // Same deal as above. | |
266 return fCurrentClipBounds; | |
267 } | |
268 } | |
269 } | |
270 | |
271 // Map the rect back to device space. | 278 // Map the rect back to device space. |
272 fCTM.mapRect(&rect); | 279 fCTM.mapRect(&rect); |
273 SkIRect devRect; | 280 SkIRect devRect; |
274 rect.roundOut(&devRect); | 281 rect.roundOut(&devRect); |
| 282 |
| 283 // Nothing can draw outside the current clip. |
| 284 // (Only bounded ops call into this method, so oddballs like Clear don't
matter here.) |
| 285 devRect.intersect(fCurrentClipBounds); |
275 return devRect; | 286 return devRect; |
276 } | 287 } |
277 | 288 |
278 // Conservative device bounds for each op in the SkRecord. | 289 // Conservative device bounds for each op in the SkRecord. |
279 SkAutoTMalloc<SkIRect> fBounds; | 290 SkAutoTMalloc<SkIRect> fBounds; |
280 | 291 |
281 // We walk fCurrentOp through the SkRecord, as we go using updateCTM() | 292 // We walk fCurrentOp through the SkRecord, as we go using updateCTM() |
282 // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative | 293 // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative |
283 // device bounds of the current clip (fCurrentClipBounds). | 294 // device bounds of the current clip (fCurrentClipBounds). |
284 unsigned fCurrentOp; | 295 unsigned fCurrentOp; |
285 SkMatrix fCTM; | 296 SkMatrix fCTM; |
286 SkIRect fCurrentClipBounds; | 297 SkIRect fCurrentClipBounds; |
287 | 298 |
288 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. | 299 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. |
289 SkTDArray<SaveBounds> fSaveStack; | 300 SkTDArray<SaveBounds> fSaveStack; |
290 SkTDArray<unsigned> fControlIndices; | 301 SkTDArray<unsigned> fControlIndices; |
291 }; | 302 }; |
292 | 303 |
293 } // namespace SkRecords | 304 } // namespace SkRecords |
294 | 305 |
295 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 306 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
296 SkRecords::FillBounds(record, bbh); | 307 SkRecords::FillBounds(record, bbh); |
297 } | 308 } |
OLD | NEW |