diff options
author | 2014-08-18 11:10:37 -0700 | |
---|---|---|
committer | 2014-08-18 11:10:37 -0700 | |
commit | 62b67ae96e94fd22569b058a3bc4625b9f52ed56 (patch) | |
tree | 7783f6c8fca68a4d4591c85fb70dff398f5c000f /src/core/SkRecordDraw.cpp | |
parent | ed265558a6a1d3b99eed76fcc0758f9a92319365 (diff) |
Start actually bounding some draw ops.
This covers most of the common draws.
BUG=skia:
R=robertphillips@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/469213007
Diffstat (limited to 'src/core/SkRecordDraw.cpp')
-rw-r--r-- | src/core/SkRecordDraw.cpp | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index e7c9575aef..bc5e7eb63f 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -238,11 +238,92 @@ private: } } - // TODO: Remove this default when done bounding all ops. + // TODO(mtklein): Remove this default when done bounding all ops. template <typename T> SkIRect bounds(const T&) const { return fCurrentClipBounds; } SkIRect bounds(const Clear&) const { return SkIRect::MakeLargest(); } // Ignores the clip SkIRect bounds(const NoOp&) const { return SkIRect::MakeEmpty(); } // NoOps don't draw. + SkIRect bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); } + SkIRect bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); } + SkIRect bounds(const DrawRRect& op) const { + return this->adjustAndMap(op.rrect.rect(), &op.paint); + } + SkIRect bounds(const DrawDRRect& op) const { + return this->adjustAndMap(op.outer.rect(), &op.paint); + } + + SkIRect bounds(const DrawBitmapRectToRect& op) const { + return this->adjustAndMap(op.dst, op.paint); + } + SkIRect bounds(const DrawBitmapNine& op) const { + return this->adjustAndMap(op.dst, op.paint); + } + SkIRect bounds(const DrawBitmap& op) const { + const SkBitmap& bm = op.bitmap; + return this->adjustAndMap(SkRect::MakeXYWH(op.left, op.top, bm.width(), bm.height()), + op.paint); + } + SkIRect bounds(const DrawBitmapMatrix& op) const { + const SkBitmap& bm = op.bitmap; + SkRect dst = SkRect::MakeWH(bm.width(), bm.height()); + op.matrix.mapRect(&dst); + return this->adjustAndMap(dst, op.paint); + } + + SkIRect bounds(const DrawPath& op) const { + return op.path.isInverseFillType() ? fCurrentClipBounds + : this->adjustAndMap(op.path.getBounds(), &op.paint); + } + SkIRect bounds(const DrawPoints& op) const { + SkRect dst; + dst.set(op.pts, op.count); + + // Pad the bounding box a little to make sure hairline points' bounds aren't empty. + SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); + dst.outset(stroke/2, stroke/2); + + return this->adjustAndMap(dst, &op.paint); + } + + SkIRect bounds(const DrawPosText& op) const { + const int N = op.paint.countText(op.text, op.byteLength); + if (N == 0) { + return SkIRect::MakeEmpty(); + } + + SkRect dst; + dst.set(op.pos, op.paint.countText(op.text, N)); + AdjustTextForFontMetrics(&dst, op.paint); + return this->adjustAndMap(dst, &op.paint); + } + SkIRect bounds(const DrawPosTextH& op) const { + const int N = op.paint.countText(op.text, op.byteLength); + if (N == 0) { + return SkIRect::MakeEmpty(); + } + + SkScalar left = op.xpos[0], right = op.xpos[0]; + for (int i = 1; i < N; i++) { + left = SkMinScalar(left, op.xpos[i]); + right = SkMaxScalar(right, op.xpos[i]); + } + SkRect dst = { left, op.y, right, op.y }; + AdjustTextForFontMetrics(&dst, op.paint); + return this->adjustAndMap(dst, &op.paint); + } + + static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { + // FIXME: These bounds should be tight (and correct), but reading SkFontMetrics is likely + // a performance bottleneck. It's safe to overapproximate these metrics for speed. E.g. + // fTop <= 1.5 * paint.getTextSize(), fXMax <= 8 * fTop, etc. + SkPaint::FontMetrics metrics; + paint.getFontMetrics(&metrics); + rect->fLeft += metrics.fXMin; + rect->fTop += metrics.fTop; + rect->fRight += metrics.fXMax; + rect->fBottom += metrics.fBottom; + } + // Returns true if rect was meaningfully adjusted for the effects of paint, // false if the paint could affect the rect in unknown ways. static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { |