diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkCanvas.cpp | 21 | ||||
-rw-r--r-- | src/core/SkMaskFilter.cpp | 16 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 89 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 1 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 11 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 32 | ||||
-rw-r--r-- | src/core/SkPictureRecord.h | 2 |
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; |