Index: Source/platform/graphics/RegionTracker.cpp |
diff --git a/Source/platform/graphics/skia/OpaqueRegionSkia.cpp b/Source/platform/graphics/RegionTracker.cpp |
similarity index 84% |
rename from Source/platform/graphics/skia/OpaqueRegionSkia.cpp |
rename to Source/platform/graphics/RegionTracker.cpp |
index 24c0369d2ee641c597367d4f4541d6d0d6364fa1..3e7a8c7eee0285a1f5569becffa92a8a47830dd1 100644 |
--- a/Source/platform/graphics/skia/OpaqueRegionSkia.cpp |
+++ b/Source/platform/graphics/RegionTracker.cpp |
@@ -30,27 +30,27 @@ |
#include "config.h" |
-#include "platform/graphics/skia/OpaqueRegionSkia.h" |
+#include "platform/graphics/RegionTracker.h" |
#include "platform/graphics/GraphicsContext.h" |
- |
-#include "SkColorFilter.h" |
-#include "SkShader.h" |
+#include "third_party/skia/include/core/SkColorFilter.h" |
+#include "third_party/skia/include/core/SkShader.h" |
namespace blink { |
-OpaqueRegionSkia::OpaqueRegionSkia() |
+RegionTracker::RegionTracker() |
: m_opaqueRect(SkRect::MakeEmpty()) |
+ , m_trackedRegionType(Opaque) |
{ |
} |
-void OpaqueRegionSkia::reset() |
+void RegionTracker::reset() |
{ |
ASSERT(m_canvasLayerStack.isEmpty()); |
m_opaqueRect = SkRect::MakeEmpty(); |
} |
-IntRect OpaqueRegionSkia::asRect() const |
+IntRect RegionTracker::asRect() const |
{ |
// Returns the largest enclosed rect. |
// TODO: actually, this logic looks like its returning the smallest. |
@@ -96,6 +96,23 @@ static inline bool xfermodeIsOpaque(const SkPaint& paint, bool srcIsOpaque) |
} |
} |
+static inline bool xfermodeIsOverwrite(const SkPaint& paint) |
+{ |
+ SkXfermode* xfermode = paint.getXfermode(); |
+ if (!xfermode) |
+ return false; // default to kSrcOver_Mode |
+ SkXfermode::Mode mode; |
+ if (!xfermode->asMode(&mode)) |
+ return false; |
+ switch (mode) { |
+ case SkXfermode::kSrc_Mode: |
+ case SkXfermode::kClear_Mode: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
// Returns true if the xfermode will keep the dst opaque, assuming the dst is already opaque. |
static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaque) |
{ |
@@ -128,11 +145,11 @@ static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaqu |
} |
// Returns true if all pixels painted will be opaque. |
-static inline bool paintIsOpaque(const SkPaint& paint, OpaqueRegionSkia::DrawType drawType, const SkBitmap* bitmap) |
+static inline bool paintIsOpaque(const SkPaint& paint, RegionTracker::DrawType drawType, const SkBitmap* bitmap) |
{ |
if (paint.getAlpha() < 0xFF) |
return false; |
- bool checkFillOnly = drawType != OpaqueRegionSkia::FillOrStroke; |
+ bool checkFillOnly = drawType != RegionTracker::FillOrStroke; |
if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias()) |
return false; |
SkShader* shader = paint.getShader(); |
@@ -168,7 +185,7 @@ static inline bool getDeviceClipAsRect(const GraphicsContext* context, SkRect& d |
return true; |
} |
-void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint) |
+void RegionTracker::pushCanvasLayer(const SkPaint* paint) |
{ |
CanvasLayerState state; |
if (paint) |
@@ -176,7 +193,7 @@ void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint) |
m_canvasLayerStack.append(state); |
} |
-void OpaqueRegionSkia::popCanvasLayer(const GraphicsContext* context) |
+void RegionTracker::popCanvasLayer(const GraphicsContext* context) |
{ |
ASSERT(!context->paintingDisabled()); |
ASSERT(!m_canvasLayerStack.isEmpty()); |
@@ -196,23 +213,23 @@ void OpaqueRegionSkia::popCanvasLayer(const GraphicsContext* context) |
applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint); |
} |
-void OpaqueRegionSkia::setImageMask(const SkRect& imageOpaqueRect) |
+void RegionTracker::setImageMask(const SkRect& imageOpaqueRect) |
{ |
ASSERT(!m_canvasLayerStack.isEmpty()); |
m_canvasLayerStack.last().hasImageMask = true; |
m_canvasLayerStack.last().imageOpaqueRect = imageOpaqueRect; |
} |
-void OpaqueRegionSkia::didDrawRect(const GraphicsContext* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap) |
+void RegionTracker::didDrawRect(const GraphicsContext* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap) |
{ |
ASSERT(!context->paintingDisabled()); |
// Any stroking may put alpha in pixels even if the filling part does not. |
if (paint.getStyle() != SkPaint::kFill_Style) { |
bool fillsBounds = false; |
- if (!paint.canComputeFastBounds()) |
+ if (!paint.canComputeFastBounds()) { |
didDrawUnbounded(context, paint, FillOrStroke); |
- else { |
+ } else { |
SkRect strokeRect; |
strokeRect = paint.computeFastBounds(fillRect, &strokeRect); |
didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillOrStroke); |
@@ -223,7 +240,7 @@ void OpaqueRegionSkia::didDrawRect(const GraphicsContext* context, const SkRect& |
didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly); |
} |
-void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath& path, const SkPaint& paint) |
+void RegionTracker::didDrawPath(const GraphicsContext* context, const SkPath& path, const SkPaint& paint) |
{ |
ASSERT(!context->paintingDisabled()); |
SkRect rect; |
@@ -234,15 +251,15 @@ void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath& |
bool fillsBounds = false; |
- if (!paint.canComputeFastBounds()) |
+ if (!paint.canComputeFastBounds()) { |
didDrawUnbounded(context, paint, FillOrStroke); |
- else { |
+ } else { |
rect = paint.computeFastBounds(path.getBounds(), &rect); |
didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); |
} |
} |
-void OpaqueRegionSkia::didDrawPoints(const GraphicsContext* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) |
+void RegionTracker::didDrawPoints(const GraphicsContext* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) |
{ |
ASSERT(!context->paintingDisabled()); |
if (!numPoints) |
@@ -263,29 +280,29 @@ void OpaqueRegionSkia::didDrawPoints(const GraphicsContext* context, SkCanvas::P |
bool fillsBounds = false; |
- if (!paint.canComputeFastBounds()) |
+ if (!paint.canComputeFastBounds()) { |
didDrawUnbounded(context, paint, FillOrStroke); |
- else { |
+ } else { |
rect = paint.computeFastBounds(rect, &rect); |
didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); |
} |
} |
-void OpaqueRegionSkia::didDrawBounded(const GraphicsContext* context, const SkRect& bounds, const SkPaint& paint) |
+void RegionTracker::didDrawBounded(const GraphicsContext* context, const SkRect& bounds, const SkPaint& paint) |
{ |
ASSERT(!context->paintingDisabled()); |
bool fillsBounds = false; |
- if (!paint.canComputeFastBounds()) |
+ if (!paint.canComputeFastBounds()) { |
didDrawUnbounded(context, paint, FillOrStroke); |
- else { |
+ } else { |
SkRect rect; |
rect = paint.computeFastBounds(bounds, &rect); |
didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); |
} |
} |
-void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType) |
+void RegionTracker::didDraw(const GraphicsContext* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType) |
{ |
ASSERT(!context->paintingDisabled()); |
SkRect targetRect = rect; |
@@ -302,17 +319,22 @@ void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rec |
else if (!targetRect.intersect(deviceClipRect)) |
return; |
+ if (m_trackedRegionType == Overwrite && fillsBounds && xfermodeIsOverwrite(paint)) { |
+ markRectAsOpaque(targetRect); |
+ return; |
+ } |
+ |
bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap); |
bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque); |
- bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque); |
- if (fillsBounds && xfersOpaque) |
+ if (fillsBounds && xfersOpaque) { |
markRectAsOpaque(targetRect); |
- else if (!preservesOpaque) |
+ } else if (m_trackedRegionType == Opaque && !xfermodePreservesOpaque(paint, drawsOpaque)) { |
markRectAsNonOpaque(targetRect); |
+ } |
} |
-void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType) |
+void RegionTracker::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType) |
{ |
ASSERT(!context->paintingDisabled()); |
bool drawsOpaque = paintIsOpaque(paint, drawType, 0); |
@@ -326,7 +348,7 @@ void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const Sk |
markRectAsNonOpaque(deviceClipRect); |
} |
-void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const GraphicsContext* context, const SkRect& layerOpaqueRect, const SkPaint& paint) |
+void RegionTracker::applyOpaqueRegionFromLayer(const GraphicsContext* context, const SkRect& layerOpaqueRect, const SkPaint& paint) |
{ |
SkRect deviceClipRect; |
bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect); |
@@ -359,7 +381,7 @@ void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const GraphicsContext* context |
markRectAsOpaque(sourceOpaqueRect); |
} |
-void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect) |
+void RegionTracker::markRectAsOpaque(const SkRect& rect) |
{ |
// We want to keep track of an opaque region but bound its complexity at a constant size. |
// We keep track of the largest rectangle seen by area. If we can add the new rect to this |
@@ -395,7 +417,7 @@ void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect) |
opaqueRect = rect; |
} |
-void OpaqueRegionSkia::markRectAsNonOpaque(const SkRect& rect) |
+void RegionTracker::markRectAsNonOpaque(const SkRect& rect) |
{ |
// We want to keep as much of the current opaque rectangle as we can, so find the one largest |
// rectangle inside m_opaqueRect that does not intersect with |rect|. |
@@ -433,13 +455,13 @@ void OpaqueRegionSkia::markRectAsNonOpaque(const SkRect& rect) |
opaqueRect = vertical; |
} |
-void OpaqueRegionSkia::markAllAsNonOpaque() |
+void RegionTracker::markAllAsNonOpaque() |
{ |
SkRect& opaqueRect = currentTrackingOpaqueRect(); |
opaqueRect.setEmpty(); |
} |
-SkRect& OpaqueRegionSkia::currentTrackingOpaqueRect() |
+SkRect& RegionTracker::currentTrackingOpaqueRect() |
{ |
// If we are drawing into a canvas layer, then track the opaque rect in that layer. |
return m_canvasLayerStack.isEmpty() ? m_opaqueRect : m_canvasLayerStack.last().opaqueRect; |