| 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 "SkPatchUtils.h" |
| 10 | 10 |
| 11 void SkRecordDraw(const SkRecord& record, | 11 void SkRecordDraw(const SkRecord& record, |
| 12 SkCanvas* canvas, | 12 SkCanvas* canvas, |
| 13 const SkBBoxHierarchy* bbh, | 13 const SkBBoxHierarchy* bbh, |
| 14 SkDrawPictureCallback* callback) { | 14 SkDrawPictureCallback* callback) { |
| 15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); | 15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); |
| 16 | 16 |
| 17 if (NULL != bbh) { | 17 if (NULL != bbh) { |
| 18 // 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. |
| 19 SkIRect query; | 19 SkIRect query; |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 fControlIndices.pop(); | 249 fControlIndices.pop(); |
| 250 } | 250 } |
| 251 | 251 |
| 252 void updateSaveBounds(const SkIRect& bounds) { | 252 void updateSaveBounds(const SkIRect& bounds) { |
| 253 // If we're in a Save block, expand its bounds to cover these bounds too
. | 253 // If we're in a Save block, expand its bounds to cover these bounds too
. |
| 254 if (!fSaveStack.isEmpty()) { | 254 if (!fSaveStack.isEmpty()) { |
| 255 fSaveStack.top().bounds.join(bounds); | 255 fSaveStack.top().bounds.join(bounds); |
| 256 } | 256 } |
| 257 } | 257 } |
| 258 | 258 |
| 259 // FIXME: these methods could use better bounds | 259 // FIXME: this method could use better bounds |
| 260 SkIRect bounds(const DrawPatch&) const { return fCurrentClipBounds; } | 260 SkIRect bounds(const DrawText&) const { return fCurrentClipBounds; } |
| 261 SkIRect bounds(const DrawPicture&) const { return fCurrentClipBounds; } | |
| 262 SkIRect bounds(const DrawTextOnPath&) const { return fCurrentClipBounds; } | |
| 263 SkIRect bounds(const DrawSprite&) const { return fCurrentClipBounds; } | |
| 264 SkIRect bounds(const DrawTextBlob&) const { return fCurrentClipBounds; } | |
| 265 SkIRect bounds(const DrawText&) const { return fCurrentClipBounds; } | |
| 266 SkIRect bounds(const DrawVertices&) const { return fCurrentClipBounds; } | |
| 267 // end of methods that could use better bounds | |
| 268 | 261 |
| 269 SkIRect bounds(const Clear&) const { return SkIRect::MakeLargest(); } // Ig
nores the clip | 262 SkIRect bounds(const Clear&) const { return SkIRect::MakeLargest(); } // Ig
nores the clip. |
| 270 SkIRect bounds(const DrawPaint&) const { return fCurrentClipBounds; } | 263 SkIRect bounds(const DrawPaint&) const { return fCurrentClipBounds; } |
| 271 SkIRect bounds(const NoOp&) const { return SkIRect::MakeEmpty(); } // No
Ops don't draw. | 264 SkIRect bounds(const NoOp&) const { return SkIRect::MakeEmpty(); } // No
Ops don't draw. |
| 272 | 265 |
| 266 SkIRect bounds(const DrawSprite& op) const { |
| 267 const SkBitmap& bm = op.bitmap; |
| 268 return SkIRect::MakeXYWH(op.left, op.top, bm.width(), bm.height()); //
Ignores the matrix. |
| 269 } |
| 270 |
| 273 SkIRect bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect
, &op.paint); } | 271 SkIRect bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect
, &op.paint); } |
| 274 SkIRect bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval
, &op.paint); } | 272 SkIRect bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval
, &op.paint); } |
| 275 SkIRect bounds(const DrawRRect& op) const { | 273 SkIRect bounds(const DrawRRect& op) const { |
| 276 return this->adjustAndMap(op.rrect.rect(), &op.paint); | 274 return this->adjustAndMap(op.rrect.rect(), &op.paint); |
| 277 } | 275 } |
| 278 SkIRect bounds(const DrawDRRect& op) const { | 276 SkIRect bounds(const DrawDRRect& op) const { |
| 279 return this->adjustAndMap(op.outer.rect(), &op.paint); | 277 return this->adjustAndMap(op.outer.rect(), &op.paint); |
| 280 } | 278 } |
| 281 | 279 |
| 282 SkIRect bounds(const DrawBitmapRectToRect& op) const { | 280 SkIRect bounds(const DrawBitmapRectToRect& op) const { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 304 SkIRect bounds(const DrawPoints& op) const { | 302 SkIRect bounds(const DrawPoints& op) const { |
| 305 SkRect dst; | 303 SkRect dst; |
| 306 dst.set(op.pts, op.count); | 304 dst.set(op.pts, op.count); |
| 307 | 305 |
| 308 // Pad the bounding box a little to make sure hairline points' bounds ar
en't empty. | 306 // Pad the bounding box a little to make sure hairline points' bounds ar
en't empty. |
| 309 SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); | 307 SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); |
| 310 dst.outset(stroke/2, stroke/2); | 308 dst.outset(stroke/2, stroke/2); |
| 311 | 309 |
| 312 return this->adjustAndMap(dst, &op.paint); | 310 return this->adjustAndMap(dst, &op.paint); |
| 313 } | 311 } |
| 312 SkIRect bounds(const DrawPatch& op) const { |
| 313 SkRect dst; |
| 314 dst.set(op.cubics, SkPatchUtils::kNumCtrlPts); |
| 315 return this->adjustAndMap(dst, &op.paint); |
| 316 } |
| 317 SkIRect bounds(const DrawVertices& op) const { |
| 318 SkRect dst; |
| 319 dst.set(op.vertices, op.vertexCount); |
| 320 return this->adjustAndMap(dst, &op.paint); |
| 321 } |
| 322 |
| 323 SkIRect bounds(const DrawPicture& op) const { |
| 324 SkRect dst = SkRect::MakeWH(op.picture->width(), op.picture->height()); |
| 325 if (op.matrix) { |
| 326 op.matrix->mapRect(&dst); |
| 327 } |
| 328 return this->adjustAndMap(dst, op.paint); |
| 329 } |
| 314 | 330 |
| 315 SkIRect bounds(const DrawPosText& op) const { | 331 SkIRect bounds(const DrawPosText& op) const { |
| 316 const int N = op.paint.countText(op.text, op.byteLength); | 332 const int N = op.paint.countText(op.text, op.byteLength); |
| 317 if (N == 0) { | 333 if (N == 0) { |
| 318 return SkIRect::MakeEmpty(); | 334 return SkIRect::MakeEmpty(); |
| 319 } | 335 } |
| 320 | 336 |
| 321 SkRect dst; | 337 SkRect dst; |
| 322 dst.set(op.pos, op.paint.countText(op.text, N)); | 338 dst.set(op.pos, op.paint.countText(op.text, N)); |
| 323 AdjustTextForFontMetrics(&dst, op.paint); | 339 AdjustTextForFontMetrics(&dst, op.paint); |
| 324 return this->adjustAndMap(dst, &op.paint); | 340 return this->adjustAndMap(dst, &op.paint); |
| 325 } | 341 } |
| 326 SkIRect bounds(const DrawPosTextH& op) const { | 342 SkIRect bounds(const DrawPosTextH& op) const { |
| 327 const int N = op.paint.countText(op.text, op.byteLength); | 343 const int N = op.paint.countText(op.text, op.byteLength); |
| 328 if (N == 0) { | 344 if (N == 0) { |
| 329 return SkIRect::MakeEmpty(); | 345 return SkIRect::MakeEmpty(); |
| 330 } | 346 } |
| 331 | 347 |
| 332 SkScalar left = op.xpos[0], right = op.xpos[0]; | 348 SkScalar left = op.xpos[0], right = op.xpos[0]; |
| 333 for (int i = 1; i < N; i++) { | 349 for (int i = 1; i < N; i++) { |
| 334 left = SkMinScalar(left, op.xpos[i]); | 350 left = SkMinScalar(left, op.xpos[i]); |
| 335 right = SkMaxScalar(right, op.xpos[i]); | 351 right = SkMaxScalar(right, op.xpos[i]); |
| 336 } | 352 } |
| 337 SkRect dst = { left, op.y, right, op.y }; | 353 SkRect dst = { left, op.y, right, op.y }; |
| 338 AdjustTextForFontMetrics(&dst, op.paint); | 354 AdjustTextForFontMetrics(&dst, op.paint); |
| 339 return this->adjustAndMap(dst, &op.paint); | 355 return this->adjustAndMap(dst, &op.paint); |
| 340 } | 356 } |
| 357 SkIRect bounds(const DrawTextOnPath& op) const { |
| 358 SkRect dst = op.path.getBounds(); |
| 359 |
| 360 // Pad all sides by the maximum padding in any direction we'd normally a
pply. |
| 361 SkRect pad = { 0, 0, 0, 0}; |
| 362 AdjustTextForFontMetrics(&pad, op.paint); |
| 363 |
| 364 // That maximum padding happens to always be the right pad today. |
| 365 SkASSERT(pad.fLeft == -pad.fRight); |
| 366 SkASSERT(pad.fTop == -pad.fBottom); |
| 367 SkASSERT(pad.fRight > pad.fBottom); |
| 368 dst.outset(pad.fRight, pad.fRight); |
| 369 |
| 370 return this->adjustAndMap(dst, &op.paint); |
| 371 } |
| 372 |
| 373 SkIRect bounds(const DrawTextBlob& op) const { |
| 374 SkRect dst = op.blob->bounds(); |
| 375 dst.offset(op.x, op.y); |
| 376 // TODO: remove when implicit bounds are plumbed through |
| 377 if (dst.isEmpty()) { |
| 378 return fCurrentClipBounds; |
| 379 } |
| 380 return this->adjustAndMap(dst, &op.paint); |
| 381 } |
| 341 | 382 |
| 342 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { | 383 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { |
| 343 #ifdef SK_DEBUG | 384 #ifdef SK_DEBUG |
| 344 SkRect correct = *rect; | 385 SkRect correct = *rect; |
| 345 #endif | 386 #endif |
| 346 const SkScalar yPad = 2.0f * paint.getTextSize(), // In practice, this
seems to be enough. | 387 const SkScalar yPad = 2.0f * paint.getTextSize(), // In practice, this
seems to be enough. |
| 347 xPad = 4.0f * yPad; // Hack for very wide
Github logo font. | 388 xPad = 4.0f * yPad; // Hack for very wide
Github logo font. |
| 348 rect->outset(xPad, yPad); | 389 rect->outset(xPad, yPad); |
| 349 #ifdef SK_DEBUG | 390 #ifdef SK_DEBUG |
| 350 SkPaint::FontMetrics metrics; | 391 SkPaint::FontMetrics metrics; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. | 458 // Used to track the bounds of Save/Restore blocks and the control ops insid
e them. |
| 418 SkTDArray<SaveBounds> fSaveStack; | 459 SkTDArray<SaveBounds> fSaveStack; |
| 419 SkTDArray<unsigned> fControlIndices; | 460 SkTDArray<unsigned> fControlIndices; |
| 420 }; | 461 }; |
| 421 | 462 |
| 422 } // namespace SkRecords | 463 } // namespace SkRecords |
| 423 | 464 |
| 424 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 465 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
| 425 SkRecords::FillBounds(record, bbh); | 466 SkRecords::FillBounds(record, bbh); |
| 426 } | 467 } |
| OLD | NEW |