Chromium Code Reviews| Index: skia/ext/analysis_canvas.cc |
| diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc |
| index 72b9eeb987bdc07adf74c3a2f6b0f5cdbe5b6faf..e6f0a29fa0e75a814e139c1eaad9ebc969e49d76 100644 |
| --- a/skia/ext/analysis_canvas.cc |
| +++ b/skia/ext/analysis_canvas.cc |
| @@ -7,6 +7,7 @@ |
| #include "third_party/skia/include/core/SkDevice.h" |
| #include "third_party/skia/include/core/SkDraw.h" |
| #include "third_party/skia/include/core/SkRRect.h" |
| +#include "third_party/skia/src/core/SkRasterClip.h" |
| #include "ui/gfx/rect_conversions.h" |
| namespace { |
| @@ -16,50 +17,123 @@ namespace { |
| // 25x as long as Z620. |
| const int gPictureCostThreshold = 1000; |
| +static bool isSolidColorPaint(const SkPaint& paint) { |
| + SkXfermode::Mode xferMode; |
| + |
| + // NULL turns into kSrcOver mode. |
|
Tom Hudson
2013/02/25 17:16:04
This comment is unclear, since NULL is nowhere in
|
| + SkXfermode::AsMode(paint.getXfermode(), &xferMode); |
| + |
| + // Paint is solid color if the following holds: |
| + // - Alpha is 1.0, style is fill, and there are no special effects |
| + // - Xfer mode is either kSrc or kSrcOver (kSrcOver is equivalent |
| + // to kSrc if source alpha is 1.0, which is already checked). |
| + return (paint.getAlpha() == 255 && |
| + !paint.getShader() && |
| + !paint.getLooper() && |
| + !paint.getMaskFilter() && |
| + !paint.getColorFilter() && |
| + paint.getStyle() == SkPaint::kFill_Style && |
| + (xferMode == SkXfermode::kSrc_Mode || |
| + xferMode == SkXfermode::kSrcOver_Mode)); |
| } |
| +} // namespace |
| + |
| namespace skia { |
| AnalysisDevice::AnalysisDevice(const SkBitmap& bm) |
| : INHERITED(bm) |
| - , estimatedCost_(0) { |
| + , estimatedCost_(0) |
| + , isForcedNotSolid_(false) |
| + , isSolidColor_(false) { |
| } |
| AnalysisDevice::~AnalysisDevice() { |
| - |
| } |
| int AnalysisDevice::getEstimatedCost() const { |
| return estimatedCost_; |
| } |
| +bool AnalysisDevice::getColorIfSolid(SkColor* color) const { |
| + if (isSolidColor_) |
| + *color = color_; |
| + return isSolidColor_; |
| +} |
| + |
| +bool AnalysisDevice::isTransparent() const { |
| + //TODO(vmpstr) implement |
| + return false; |
| +} |
| + |
| +void AnalysisDevice::setForceNotSolid(bool flag) { |
| + isForcedNotSolid_ = flag; |
| + if (isForcedNotSolid_) |
| + isSolidColor_ = false; |
| +} |
| + |
| void AnalysisDevice::clear(SkColor color) { |
| - ++estimatedCost_; |
| + ++estimatedCost_; |
| + if (!isForcedNotSolid_ && SkColorGetA(color) == 255) { |
| + isSolidColor_ = true; |
| + color_ = color; |
| + } |
| + else { |
| + isSolidColor_ = false; |
| + } |
| } |
| void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, |
| size_t count, const SkPoint[], |
| const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| -void AnalysisDevice::drawRect(const SkDraw&, const SkRect& r, |
| +void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect, |
| const SkPaint& paint) { |
| // FIXME: if there's a pending image decode & resize, more expensive |
| if (paint.getMaskFilter()) { |
| estimatedCost_ += 300; |
| } |
| ++estimatedCost_; |
| + |
| + if (isForcedNotSolid_) |
| + return; |
| + |
| + SkRect clipRect = SkRect::Make(draw.fRC->getBounds()); |
| + SkRect bitmapRect = SkRect::MakeWH(width(), height()); |
| + |
| + // This bitmap is solid if and only if the following holds. |
| + // Note that this might be overly conservative: |
| + // - Paint is solid color |
| + // - Clip rect is an actual rectangle. |
| + // - The rect we're drawing contains the clip rect. |
| + // That is, all of clip rect will be colored by the rect. |
| + // - Clip rect contains the bitmap rect. |
| + // That is, we're not clipping to a portion of this bitmap. |
|
Tom Hudson
2013/02/25 17:16:04
You mention "bitmap", but when we're on the border
|
| + if (isSolidColorPaint(paint) && |
| + draw.fRC->isRect() && |
| + rect.contains(clipRect) && |
| + clipRect.contains(bitmapRect)) { |
| + isSolidColor_ = true; |
| + color_ = paint.getColor(); |
| + } |
| + else { |
| + isSolidColor_ = false; |
| + } |
| } |
| void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval, |
| const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, |
| @@ -73,6 +147,7 @@ void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, |
| estimatedCost_ += 300; |
| } |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, |
| @@ -80,17 +155,20 @@ void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, |
| const SkMatrix& matrix, const SkPaint& paint) |
| { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, |
| int x, int y, const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, |
| const SkRect* srcOrNull, const SkRect& dst, |
| const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| @@ -98,6 +176,7 @@ void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len, |
| SkScalar x, SkScalar y, const SkPaint& paint) |
| { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, |
| @@ -106,12 +185,14 @@ void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le |
| // FIXME: On Z620, every glyph cache miss costs us about 10us. |
| // We don't have a good mechanism for predicting glyph cache misses. |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, |
| const SkPath& path, const SkMatrix* matrix, |
| const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| #ifdef SK_BUILD_FOR_ANDROID |
| @@ -121,6 +202,7 @@ void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, |
| const SkPath& path, const SkMatrix* matrix) |
| { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| #endif |
| @@ -131,19 +213,21 @@ void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, |
| const uint16_t indices[], int indexCount, |
| const SkPaint& paint) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y, |
| const SkPaint&) { |
| ++estimatedCost_; |
| + isSolidColor_ = false; |
| } |
| AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device) |
| - : INHERITED(device) { |
| - |
| + : INHERITED(device) |
| + , saveDepth_(0) { |
| } |
| AnalysisCanvas::~AnalysisCanvas() { |
| @@ -154,11 +238,18 @@ bool AnalysisCanvas::isCheap() const { |
| return getEstimatedCost() < gPictureCostThreshold; |
| } |
| +bool AnalysisCanvas::getColorIfSolid(SkColor* color) const { |
| + return (static_cast<AnalysisDevice*>(getDevice()))->getColorIfSolid(color); |
| +} |
| + |
| +bool AnalysisCanvas::isTransparent() const { |
| + return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent(); |
| +} |
| + |
| int AnalysisCanvas::getEstimatedCost() const { |
| return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost(); |
| } |
| - |
| bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, |
| bool doAA) { |
| return INHERITED::clipRect(rect, op, doAA); |
| @@ -174,17 +265,27 @@ bool AnalysisCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, |
| return INHERITED::clipRect(rrect.getBounds(), op, doAA); |
| } |
| -int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint*, |
| +int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, |
| SkCanvas::SaveFlags flags) { |
| + if (paint && !isSolidColorPaint(*paint)) |
| + (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(true); |
| + ++saveDepth_; |
| + |
| // Actually saving a layer here could cause a new bitmap to be created |
| // and real rendering to occur. |
| - int count = SkCanvas::save(flags); |
| + int count = INHERITED::save(flags); |
| if (bounds) { |
| INHERITED::clipRectBounds(bounds, flags, NULL); |
| } |
| return count; |
| } |
| +void AnalysisCanvas::restore() { |
| + INHERITED::restore(); |
| + if (--saveDepth_ == 0) |
| + (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(false); |
|
Tom Hudson
2013/02/25 17:16:04
This looks really conservative: if we ever save a
|
| +} |
| + |
| } // namespace skia |