aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkCanvas.cpp21
-rw-r--r--src/core/SkMaskFilter.cpp16
-rw-r--r--src/core/SkPaint.cpp89
-rw-r--r--src/core/SkPictureFlat.h1
-rw-r--r--src/core/SkPicturePlayback.cpp11
-rw-r--r--src/core/SkPictureRecord.cpp32
-rw-r--r--src/core/SkPictureRecord.h2
7 files changed, 141 insertions, 31 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index ed65eca725..306a0f4e45 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1397,11 +1397,15 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
SkDEBUGCODE(bitmap.validate();)
if (NULL == paint || paint->canComputeFastBounds()) {
- SkRect fastBounds;
- fastBounds.set(x, y,
- x + SkIntToScalar(bitmap.width()),
- y + SkIntToScalar(bitmap.height()));
- if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
+ SkRect bounds = {
+ x, y,
+ x + SkIntToScalar(bitmap.width()),
+ y + SkIntToScalar(bitmap.height())
+ };
+ if (paint) {
+ (void)paint->computeFastBounds(bounds, &bounds);
+ }
+ if (this->quickReject(bounds, paint2EdgeType(paint))) {
return;
}
}
@@ -1420,7 +1424,12 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src
// do this now, to avoid the cost of calling extract for RLE bitmaps
if (NULL == paint || paint->canComputeFastBounds()) {
- if (this->quickReject(dst, paint2EdgeType(paint))) {
+ SkRect storage;
+ const SkRect* bounds = &dst;
+ if (paint) {
+ bounds = &paint->computeFastBounds(dst, &storage);
+ }
+ if (this->quickReject(*bounds, paint2EdgeType(paint))) {
return;
}
}
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp
index 3bdca10229..42d07a6db0 100644
--- a/src/core/SkMaskFilter.cpp
+++ b/src/core/SkMaskFilter.cpp
@@ -56,4 +56,20 @@ SkMaskFilter::BlurType SkMaskFilter::asABlur(BlurInfo*) const {
return kNone_BlurType;
}
+void SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) {
+ SkMask srcM, dstM;
+
+ srcM.fImage = NULL;
+ src.roundOut(&srcM.fBounds);
+ srcM.fRowBytes = 0;
+ srcM.fFormat = SkMask::kA8_Format;
+
+ SkIPoint margin; // ignored
+ if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) {
+ dst->set(dstM.fBounds);
+ } else {
+ dst->set(srcM.fBounds);
+ }
+}
+
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index cf25dbf9ee..7d418f4b1c 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -9,7 +9,6 @@
#include "SkPaint.h"
#include "SkColorFilter.h"
-#include "SkDrawLooper.h"
#include "SkFontHost.h"
#include "SkImageFilter.h"
#include "SkMaskFilter.h"
@@ -1847,23 +1846,38 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
}
-const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
- SkRect* storage) const {
+const SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
+ SkRect* storage) const {
SkASSERT(storage);
- SkASSERT(this->getStyle() != SkPaint::kFill_Style);
-
- // since we're stroked, outset the rect by the radius (and join type)
- SkScalar radius = SkScalarHalf(this->getStrokeWidth());
- if (0 == radius) { // hairline
- radius = SK_Scalar1;
- } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
- SkScalar scale = this->getStrokeMiter();
- if (scale > SK_Scalar1) {
- radius = SkScalarMul(radius, scale);
+
+ if (this->getLooper()) {
+ SkASSERT(this->getLooper()->canComputeFastBounds(*this));
+ this->getLooper()->computeFastBounds(*this, src, storage);
+ return *storage;
+ }
+
+ if (this->getStyle() != SkPaint::kFill_Style) {
+ // since we're stroked, outset the rect by the radius (and join type)
+ SkScalar radius = SkScalarHalf(this->getStrokeWidth());
+ if (0 == radius) { // hairline
+ radius = SK_Scalar1;
+ } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
+ SkScalar scale = this->getStrokeMiter();
+ if (scale > SK_Scalar1) {
+ radius = SkScalarMul(radius, scale);
+ }
}
+ storage->set(src.fLeft - radius, src.fTop - radius,
+ src.fRight + radius, src.fBottom + radius);
+ } else {
+ *storage = src;
}
- storage->set(src.fLeft - radius, src.fTop - radius,
- src.fRight + radius, src.fBottom + radius);
+
+ // check the mask filter
+ if (this->getMaskFilter()) {
+ this->getMaskFilter()->computeFastBounds(*storage, storage);
+ }
+
return *storage;
}
@@ -2021,3 +2035,48 @@ bool SkImageFilter::asABlur(SkSize* sigma) const {
return false;
}
+//////
+
+bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
+ SkCanvas canvas;
+
+ this->init(&canvas);
+ for (;;) {
+ SkPaint p(paint);
+ if (this->next(&canvas, &p)) {
+ p.setLooper(NULL);
+ if (!p.canComputeFastBounds()) {
+ return false;
+ }
+ } else {
+ break;
+ }
+ }
+ return true;
+}
+
+void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
+ SkRect* dst) {
+ SkCanvas canvas;
+
+ this->init(&canvas);
+ for (bool firstTime = true;; firstTime = false) {
+ SkPaint p(paint);
+ if (this->next(&canvas, &p)) {
+ SkRect r(src);
+
+ p.setLooper(NULL);
+ p.computeFastBounds(r, &r);
+ canvas.getTotalMatrix().mapRect(&r);
+
+ if (firstTime) {
+ *dst = r;
+ } else {
+ dst->join(r);
+ }
+ } else {
+ break;
+ }
+ }
+}
+
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index bd212b827f..983bfc5f25 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -33,6 +33,7 @@ enum DrawType {
DRAW_PICTURE,
DRAW_POINTS,
DRAW_POS_TEXT,
+ DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
DRAW_POS_TEXT_H,
DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
DRAW_RECT,
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index d922051e3f..c2082c7e37 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -606,6 +606,17 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
const SkPoint* pos = (const SkPoint*)fReader.skip(points * sizeof(SkPoint));
canvas.drawPosText(text.text(), text.length(), pos, paint);
} break;
+ case DRAW_POS_TEXT_TOP_BOTTOM: {
+ const SkPaint& paint = *getPaint();
+ getText(&text);
+ size_t points = getInt();
+ const SkPoint* pos = (const SkPoint*)fReader.skip(points * sizeof(SkPoint));
+ const SkScalar top = fReader.readScalar();
+ const SkScalar bottom = fReader.readScalar();
+ if (!canvas.quickRejectY(top, bottom, SkCanvas::kAA_EdgeType)) {
+ canvas.drawPosText(text.text(), text.length(), pos, paint);
+ }
+ } break;
case DRAW_POS_TEXT_H: {
const SkPaint& paint = *getPaint();
getText(&text);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 1c57c04b23..f31065b444 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -287,14 +287,14 @@ void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
}
void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
- SkScalar baselineY) {
+ SkScalar minY, SkScalar maxY) {
SkPaint::FontMetrics metrics;
paint.getFontMetrics(&metrics);
SkRect bounds;
// construct a rect so we can see any adjustments from the paint.
// we use 0,1 for left,right, just so the rect isn't empty
- bounds.set(0, metrics.fTop + baselineY,
- SK_Scalar1, metrics.fBottom + baselineY);
+ bounds.set(0, metrics.fTop + minY,
+ SK_Scalar1, metrics.fBottom + maxY);
(void)paint.computeFastBounds(bounds, &bounds);
// now record the top and bottom
addScalar(bounds.fTop);
@@ -311,7 +311,7 @@ void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
addScalar(x);
addScalar(y);
if (fast) {
- addFontMetricsTopBottom(paint, y);
+ addFontMetricsTopBottom(paint, y, y);
}
validate();
}
@@ -323,23 +323,34 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
return;
bool canUseDrawH = true;
+ SkScalar minY = pos[0].fY;
+ SkScalar maxY = pos[0].fY;
// check if the caller really should have used drawPosTextH()
{
const SkScalar firstY = pos[0].fY;
for (size_t index = 1; index < points; index++) {
if (pos[index].fY != firstY) {
canUseDrawH = false;
- break;
+ if (pos[index].fY < minY) {
+ minY = pos[index].fY;
+ } else if (pos[index].fY > maxY) {
+ maxY = pos[index].fY;
+ }
}
}
}
- bool fast = canUseDrawH && paint.canComputeFastBounds();
+ bool fastBounds = paint.canComputeFastBounds();
+ bool fast = canUseDrawH && fastBounds;
if (fast) {
addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
+ } else if (canUseDrawH) {
+ addDraw(DRAW_POS_TEXT_H);
+ } else if (fastBounds) {
+ addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
} else {
- addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
+ addDraw(DRAW_POS_TEXT);
}
addPaint(paint);
addText(text, byteLength);
@@ -350,7 +361,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
#endif
if (canUseDrawH) {
if (fast) {
- addFontMetricsTopBottom(paint, pos[0].fY);
+ addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
}
addScalar(pos[0].fY);
SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
@@ -359,6 +370,9 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
}
else {
fWriter.writeMul4(pos, points * sizeof(SkPoint));
+ if (fastBounds) {
+ addFontMetricsTopBottom(paint, minY, maxY);
+ }
}
#ifdef SK_DEBUG_SIZE
fPointBytes += fWriter.size() - start;
@@ -385,7 +399,7 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
size_t start = fWriter.size();
#endif
if (fast) {
- addFontMetricsTopBottom(paint, constY);
+ addFontMetricsTopBottom(paint, constY, constY);
}
addScalar(constY);
fWriter.writeMul4(xpos, points * sizeof(SkScalar));
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 77f7173faa..ff6585d375 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -66,7 +66,7 @@ public:
const SkPaint&) SK_OVERRIDE;
virtual void drawData(const void*, size_t) SK_OVERRIDE;
- void addFontMetricsTopBottom(const SkPaint& paint, SkScalar baselineY);
+ void addFontMetricsTopBottom(const SkPaint& paint, SkScalar minY, SkScalar maxY);
const SkTDArray<const SkFlatBitmap* >& getBitmaps() const {
return fBitmaps;