Index: skia/ext/analysis_canvas.cc |
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc |
deleted file mode 100644 |
index cb2d82be2d6f92821cba5fd803d5ad175218e5f5..0000000000000000000000000000000000000000 |
--- a/skia/ext/analysis_canvas.cc |
+++ /dev/null |
@@ -1,454 +0,0 @@ |
-// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "base/logging.h" |
-#include "base/trace_event/trace_event.h" |
-#include "skia/ext/analysis_canvas.h" |
-#include "third_party/skia/include/core/SkDraw.h" |
-#include "third_party/skia/include/core/SkPath.h" |
-#include "third_party/skia/include/core/SkRRect.h" |
-#include "third_party/skia/include/core/SkShader.h" |
-#include "third_party/skia/src/core/SkRasterClip.h" |
- |
-namespace { |
- |
-const int kNoLayer = -1; |
- |
-bool ActsLikeClear(SkXfermode::Mode mode, unsigned src_alpha) { |
- switch (mode) { |
- case SkXfermode::kClear_Mode: |
- return true; |
- case SkXfermode::kSrc_Mode: |
- case SkXfermode::kSrcIn_Mode: |
- case SkXfermode::kDstIn_Mode: |
- case SkXfermode::kSrcOut_Mode: |
- case SkXfermode::kDstATop_Mode: |
- return src_alpha == 0; |
- case SkXfermode::kDstOut_Mode: |
- return src_alpha == 0xFF; |
- default: |
- return false; |
- } |
-} |
- |
-bool IsSolidColorPaint(const SkPaint& paint) { |
- SkXfermode::Mode xfermode; |
- |
- // getXfermode can return a NULL, but that is handled |
- // gracefully by AsMode (NULL turns into kSrcOver mode). |
- 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.getImageFilter() && |
- paint.getStyle() == SkPaint::kFill_Style && |
- (xfermode == SkXfermode::kSrc_Mode || |
- xfermode == SkXfermode::kSrcOver_Mode)); |
-} |
- |
-// Returns true if the specified drawn_rect will cover the entire canvas, and |
-// that the canvas is not clipped (i.e. it covers ALL of the canvas). |
-bool IsFullQuad(SkCanvas* canvas, const SkRect& drawn_rect) { |
- if (!canvas->isClipRect()) |
- return false; |
- |
- SkIRect clip_irect; |
- canvas->getClipDeviceBounds(&clip_irect); |
- // if the clip is smaller than the canvas, we're partly clipped, so abort. |
- if (!clip_irect.contains(SkIRect::MakeSize(canvas->getDeviceSize()))) |
- return false; |
- |
- const SkMatrix& matrix = canvas->getTotalMatrix(); |
- // If the transform results in a non-axis aligned |
- // rect, then be conservative and return false. |
- if (!matrix.rectStaysRect()) |
- return false; |
- |
- SkRect device_rect; |
- matrix.mapRect(&device_rect, drawn_rect); |
- SkRect clip_rect; |
- clip_rect.set(clip_irect); |
- return device_rect.contains(clip_rect); |
-} |
- |
-} // namespace |
- |
-namespace skia { |
- |
-void AnalysisCanvas::SetForceNotSolid(bool flag) { |
- is_forced_not_solid_ = flag; |
- if (is_forced_not_solid_) |
- is_solid_color_ = false; |
-} |
- |
-void AnalysisCanvas::SetForceNotTransparent(bool flag) { |
- is_forced_not_transparent_ = flag; |
- if (is_forced_not_transparent_) |
- is_transparent_ = false; |
-} |
- |
-void AnalysisCanvas::onDrawPaint(const SkPaint& paint) { |
- SkRect rect; |
- getClipBounds(&rect); |
- drawRect(rect, paint); |
-} |
- |
-void AnalysisCanvas::onDrawPoints(SkCanvas::PointMode mode, |
- size_t count, |
- const SkPoint points[], |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { |
- // This recreates the early-exit logic in SkCanvas.cpp. |
- SkRect scratch; |
- if (paint.canComputeFastBounds() && |
- quickReject(paint.computeFastBounds(rect, &scratch))) { |
- return; |
- } |
- |
- // An extra no-op check SkCanvas.cpp doesn't do. |
- if (paint.nothingToDraw()) |
- return; |
- |
- bool does_cover_canvas = IsFullQuad(this, rect); |
- |
- SkXfermode::Mode xfermode; |
- SkXfermode::AsMode(paint.getXfermode(), &xfermode); |
- |
- // This canvas will become transparent if the following holds: |
- // - The quad is a full tile quad |
- // - We're not in "forced not transparent" mode |
- // - Transfer mode is clear (0 color, 0 alpha) |
- // |
- // If the paint alpha is not 0, or if the transfrer mode is |
- // not src, then this canvas will not be transparent. |
- // |
- // In all other cases, we keep the current transparent value |
- if (does_cover_canvas && |
- !is_forced_not_transparent_ && |
- ActsLikeClear(xfermode, paint.getAlpha())) { |
- is_transparent_ = true; |
- } else if (paint.getAlpha() != 0 || xfermode != SkXfermode::kSrc_Mode) { |
- is_transparent_ = false; |
- } |
- |
- // This bitmap is solid if and only if the following holds. |
- // Note that this might be overly conservative: |
- // - We're not in "forced not solid" mode |
- // - Paint is solid color |
- // - The quad is a full tile quad |
- if (!is_forced_not_solid_ && IsSolidColorPaint(paint) && does_cover_canvas) { |
- is_solid_color_ = true; |
- color_ = paint.getColor(); |
- } else { |
- is_solid_color_ = false; |
- } |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawRRect(const SkRRect& rr, const SkPaint& paint) { |
- // This should add the SkRRect to an SkPath, and call |
- // drawPath, but since drawPath ignores the SkPath, just |
- // do the same work here. |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawBitmap(const SkBitmap& bitmap, |
- SkScalar left, |
- SkScalar top, |
- const SkPaint*) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawBitmapRect(const SkBitmap&, |
- const SkRect* src, |
- const SkRect& dst, |
- const SkPaint* paint, |
- SrcRectConstraint flags) { |
- // Call drawRect to determine transparency, |
- // but reset solid color to false. |
- SkPaint tmpPaint; |
- if (!paint) |
- paint = &tmpPaint; |
- drawRect(dst, *paint); |
- is_solid_color_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawBitmapNine(const SkBitmap& bitmap, |
- const SkIRect& center, |
- const SkRect& dst, |
- const SkPaint* paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawSprite(const SkBitmap& bitmap, |
- int left, |
- int top, |
- const SkPaint* paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawText(const void* text, |
- size_t len, |
- SkScalar x, |
- SkScalar y, |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawPosText(const void* text, |
- size_t byteLength, |
- const SkPoint pos[], |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawPosTextH(const void* text, |
- size_t byteLength, |
- const SkScalar xpos[], |
- SkScalar constY, |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawTextOnPath(const void* text, |
- size_t len, |
- const SkPath& path, |
- const SkMatrix* matrix, |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawTextBlob(const SkTextBlob* blob, |
- SkScalar x, |
- SkScalar y, |
- const SkPaint &paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawDRRect(const SkRRect& outer, |
- const SkRRect& inner, |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-void AnalysisCanvas::onDrawVertices(SkCanvas::VertexMode, |
- int vertex_count, |
- const SkPoint verts[], |
- const SkPoint texs[], |
- const SkColor colors[], |
- SkXfermode* xmode, |
- const uint16_t indices[], |
- int index_count, |
- const SkPaint& paint) { |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- ++draw_op_count_; |
-} |
- |
-// Needed for now, since SkCanvas requires a bitmap, even if it is not backed |
-// by any pixels |
-static SkBitmap MakeEmptyBitmap(int width, int height) { |
- SkBitmap bitmap; |
- bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); |
- return bitmap; |
-} |
- |
-AnalysisCanvas::AnalysisCanvas(int width, int height) |
- : INHERITED(MakeEmptyBitmap(width, height)), |
- saved_stack_size_(0), |
- force_not_solid_stack_level_(kNoLayer), |
- force_not_transparent_stack_level_(kNoLayer), |
- is_forced_not_solid_(false), |
- is_forced_not_transparent_(false), |
- is_solid_color_(true), |
- color_(SK_ColorTRANSPARENT), |
- is_transparent_(true), |
- draw_op_count_(0) { |
-} |
- |
-AnalysisCanvas::~AnalysisCanvas() {} |
- |
-bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { |
- if (is_transparent_) { |
- *color = SK_ColorTRANSPARENT; |
- return true; |
- } |
- if (is_solid_color_) { |
- *color = color_; |
- return true; |
- } |
- return false; |
-} |
- |
-bool AnalysisCanvas::abort() { |
- // Early out as soon as we have more than one draw op. |
- // TODO(vmpstr): Investigate if 1 is the correct metric here. We need to |
- // balance the amount of time we spend analyzing vs how many tiles would be |
- // solid if the number was higher. |
- if (draw_op_count_ > 1) { |
- // We have to reset solid/transparent state to false since we don't |
- // know whether consequent operations will make this false. |
- is_solid_color_ = false; |
- is_transparent_ = false; |
- return true; |
- } |
- return false; |
-} |
- |
-void AnalysisCanvas::OnComplexClip() { |
- // complex clips can make our calls to IsFullQuad invalid (ie have false |
- // positives). As a precaution, force the setting to be non-solid |
- // and non-transparent until we pop this |
- if (force_not_solid_stack_level_ == kNoLayer) { |
- force_not_solid_stack_level_ = saved_stack_size_; |
- SetForceNotSolid(true); |
- } |
- if (force_not_transparent_stack_level_ == kNoLayer) { |
- force_not_transparent_stack_level_ = saved_stack_size_; |
- SetForceNotTransparent(true); |
- } |
-} |
- |
-void AnalysisCanvas::onClipRect(const SkRect& rect, |
- SkRegion::Op op, |
- ClipEdgeStyle edge_style) { |
- INHERITED::onClipRect(rect, op, edge_style); |
-} |
- |
-void AnalysisCanvas::onClipPath(const SkPath& path, |
- SkRegion::Op op, |
- ClipEdgeStyle edge_style) { |
- OnComplexClip(); |
- INHERITED::onClipRect(path.getBounds(), op, edge_style); |
-} |
- |
-void AnalysisCanvas::onClipRRect(const SkRRect& rrect, |
- SkRegion::Op op, |
- ClipEdgeStyle edge_style) { |
- OnComplexClip(); |
- INHERITED::onClipRect(rrect.getBounds(), op, edge_style); |
-} |
- |
-void AnalysisCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { |
- const ClipEdgeStyle edge_style = kHard_ClipEdgeStyle; |
- if (deviceRgn.isRect()) { |
- onClipRect(SkRect::MakeFromIRect(deviceRgn.getBounds()), op, edge_style); |
- return; |
- } |
- OnComplexClip(); |
- INHERITED::onClipRect( |
- SkRect::MakeFromIRect(deviceRgn.getBounds()), op, edge_style); |
-} |
- |
-void AnalysisCanvas::willSave() { |
- ++saved_stack_size_; |
- INHERITED::willSave(); |
-} |
- |
-SkCanvas::SaveLayerStrategy AnalysisCanvas::willSaveLayer( |
- const SkRect* bounds, |
- const SkPaint* paint, |
- SkCanvas::SaveFlags flags) { |
- |
- ++saved_stack_size_; |
- |
- SkIRect canvas_ibounds = SkIRect::MakeSize(this->getDeviceSize()); |
- SkRect canvas_bounds; |
- canvas_bounds.set(canvas_ibounds); |
- |
- // If after we draw to the saved layer, we have to blend with the current |
- // layer, then we can conservatively say that the canvas will not be of |
- // solid color. |
- if ((paint && !IsSolidColorPaint(*paint)) || |
- (bounds && !bounds->contains(canvas_bounds))) { |
- if (force_not_solid_stack_level_ == kNoLayer) { |
- force_not_solid_stack_level_ = saved_stack_size_; |
- SetForceNotSolid(true); |
- } |
- } |
- |
- // If after we draw to the save layer, we have to blend with the current |
- // layer using any part of the current layer's alpha, then we can |
- // conservatively say that the canvas will not be transparent. |
- SkXfermode::Mode xfermode = SkXfermode::kSrc_Mode; |
- if (paint) |
- SkXfermode::AsMode(paint->getXfermode(), &xfermode); |
- if (xfermode != SkXfermode::kDst_Mode) { |
- if (force_not_transparent_stack_level_ == kNoLayer) { |
- force_not_transparent_stack_level_ = saved_stack_size_; |
- SetForceNotTransparent(true); |
- } |
- } |
- |
- INHERITED::willSaveLayer(bounds, paint, flags); |
- // Actually saving a layer here could cause a new bitmap to be created |
- // and real rendering to occur. |
- return kNoLayer_SaveLayerStrategy; |
-} |
- |
-void AnalysisCanvas::willRestore() { |
- DCHECK(saved_stack_size_); |
- if (saved_stack_size_) { |
- --saved_stack_size_; |
- if (saved_stack_size_ < force_not_solid_stack_level_) { |
- SetForceNotSolid(false); |
- force_not_solid_stack_level_ = kNoLayer; |
- } |
- if (saved_stack_size_ < force_not_transparent_stack_level_) { |
- SetForceNotTransparent(false); |
- force_not_transparent_stack_level_ = kNoLayer; |
- } |
- } |
- |
- INHERITED::willRestore(); |
-} |
- |
-} // namespace skia |
- |
- |