Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(822)

Unified Diff: Source/core/platform/graphics/skia/OpaqueRegionSkia.cpp

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/platform/graphics/skia/OpaqueRegionSkia.cpp
diff --git a/Source/core/platform/graphics/skia/OpaqueRegionSkia.cpp b/Source/core/platform/graphics/skia/OpaqueRegionSkia.cpp
deleted file mode 100644
index 493350acf4a8728a87523137740256857a7eaacb..0000000000000000000000000000000000000000
--- a/Source/core/platform/graphics/skia/OpaqueRegionSkia.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (c) 2012, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "core/platform/graphics/skia/OpaqueRegionSkia.h"
-
-#include "core/platform/graphics/GraphicsContext.h"
-
-#include "SkColorFilter.h"
-#include "SkShader.h"
-
-namespace WebCore {
-
-OpaqueRegionSkia::OpaqueRegionSkia()
- : m_opaqueRect(SkRect::MakeEmpty())
-{
-}
-
-IntRect OpaqueRegionSkia::asRect() const
-{
- // Returns the largest enclosed rect.
- int left = SkScalarCeil(m_opaqueRect.fLeft);
- int top = SkScalarCeil(m_opaqueRect.fTop);
- int right = SkScalarFloor(m_opaqueRect.fRight);
- int bottom = SkScalarFloor(m_opaqueRect.fBottom);
- return IntRect(left, top, right-left, bottom-top);
-}
-
-// Returns true if the xfermode will force the dst to be opaque, regardless of the current dst.
-static inline bool xfermodeIsOpaque(const SkPaint& paint, bool srcIsOpaque)
-{
- if (!srcIsOpaque)
- return false;
-
- SkXfermode* xfermode = paint.getXfermode();
- if (!xfermode)
- return true; // default to kSrcOver_Mode
- SkXfermode::Mode mode;
- if (!xfermode->asMode(&mode))
- return false;
-
- switch (mode) {
- case SkXfermode::kSrc_Mode: // source
- case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
- case SkXfermode::kDstOver_Mode: // source + dest - source*dest
- case SkXfermode::kDstATop_Mode: // source
- case SkXfermode::kPlus_Mode: // source+dest
- default: // the rest are all source + dest - source*dest
- return true;
- case SkXfermode::kClear_Mode: // 0
- case SkXfermode::kDst_Mode: // dest
- case SkXfermode::kSrcIn_Mode: // source * dest
- case SkXfermode::kDstIn_Mode: // dest * source
- case SkXfermode::kSrcOut_Mode: // source * (1-dest)
- case SkXfermode::kDstOut_Mode: // dest * (1-source)
- case SkXfermode::kSrcATop_Mode: // dest
- case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
- 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)
-{
- SkXfermode* xfermode = paint.getXfermode();
- if (!xfermode)
- return true; // default to kSrcOver_Mode
- SkXfermode::Mode mode;
- if (!xfermode->asMode(&mode))
- return false;
-
- switch (mode) {
- case SkXfermode::kDst_Mode: // dest
- case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
- case SkXfermode::kDstOver_Mode: // source + dest - source*dest
- case SkXfermode::kSrcATop_Mode: // dest
- case SkXfermode::kPlus_Mode: // source+dest
- default: // the rest are all source + dest - source*dest
- return true;
- case SkXfermode::kClear_Mode: // 0
- case SkXfermode::kSrcOut_Mode: // source * (1-dest)
- case SkXfermode::kDstOut_Mode: // dest * (1-source)
- case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
- return false;
- case SkXfermode::kSrc_Mode: // source
- case SkXfermode::kSrcIn_Mode: // source * dest
- case SkXfermode::kDstIn_Mode: // dest * source
- case SkXfermode::kDstATop_Mode: // source
- return srcIsOpaque;
- }
-}
-
-// Returns true if all pixels painted will be opaque.
-static inline bool paintIsOpaque(const SkPaint& paint, OpaqueRegionSkia::DrawType drawType, const SkBitmap* bitmap)
-{
- if (paint.getAlpha() < 0xFF)
- return false;
- bool checkFillOnly = drawType != OpaqueRegionSkia::FillOrStroke;
- if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias())
- return false;
- SkShader* shader = paint.getShader();
- if (shader && !shader->isOpaque())
- return false;
- if (bitmap && !bitmap->isOpaque())
- return false;
- if (paint.getLooper())
- return false;
- if (paint.getImageFilter())
- return false;
- if (paint.getMaskFilter())
- return false;
- SkColorFilter* colorFilter = paint.getColorFilter();
- if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag))
- return false;
- return true;
-}
-
-// Returns true if there is a rectangular clip, with the result in |deviceClipRect|.
-static inline bool getDeviceClipAsRect(const GraphicsContext* context, SkRect& deviceClipRect)
-{
- // Get the current clip in device coordinate space.
- if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
- return false;
-
- SkIRect deviceClipIRect;
- if (context->canvas()->getClipDeviceBounds(&deviceClipIRect))
- deviceClipRect.set(deviceClipIRect);
- else
- deviceClipRect.setEmpty();
-
- return true;
-}
-
-void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint)
-{
- CanvasLayerState state;
- if (paint)
- state.paint = *paint;
- m_canvasLayerStack.append(state);
-}
-
-void OpaqueRegionSkia::popCanvasLayer(const GraphicsContext* context)
-{
- ASSERT(!m_canvasLayerStack.isEmpty());
- if (m_canvasLayerStack.isEmpty())
- return;
-
- const CanvasLayerState& canvasLayer = m_canvasLayerStack.last();
- SkRect layerOpaqueRect = canvasLayer.opaqueRect;
- SkPaint layerPaint = canvasLayer.paint;
-
- // Apply the image mask.
- if (canvasLayer.hasImageMask && !layerOpaqueRect.intersect(canvasLayer.imageOpaqueRect))
- layerOpaqueRect.setEmpty();
-
- m_canvasLayerStack.removeLast();
-
- applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint);
-}
-
-void OpaqueRegionSkia::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)
-{
- // 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())
- didDrawUnbounded(context, paint, FillOrStroke);
- else {
- SkRect strokeRect;
- strokeRect = paint.computeFastBounds(fillRect, &strokeRect);
- didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillOrStroke);
- }
- }
-
- bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style;
- didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly);
-}
-
-void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath& path, const SkPaint& paint)
-{
- SkRect rect;
- if (path.isRect(&rect)) {
- didDrawRect(context, rect, paint, 0);
- return;
- }
-
- bool fillsBounds = false;
-
- if (!paint.canComputeFastBounds())
- didDrawUnbounded(context, paint, FillOrStroke);
- 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)
-{
- if (!numPoints)
- return;
-
- SkRect rect;
- rect.fLeft = points[0].fX;
- rect.fRight = points[0].fX + 1;
- rect.fTop = points[0].fY;
- rect.fBottom = points[0].fY + 1;
-
- for (int i = 1; i < numPoints; ++i) {
- rect.fLeft = std::min(rect.fLeft, points[i].fX);
- rect.fRight = std::max(rect.fRight, points[i].fX + 1);
- rect.fTop = std::min(rect.fTop, points[i].fY);
- rect.fBottom = std::max(rect.fBottom, points[i].fY + 1);
- }
-
- bool fillsBounds = false;
-
- if (!paint.canComputeFastBounds())
- didDrawUnbounded(context, paint, FillOrStroke);
- 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)
-{
- bool fillsBounds = false;
-
- if (!paint.canComputeFastBounds())
- didDrawUnbounded(context, paint, FillOrStroke);
- 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)
-{
- SkRect targetRect = rect;
-
- // Apply the transform to device coordinate space.
- SkMatrix canvasTransform = context->canvas()->getTotalMatrix();
- if (!canvasTransform.mapRect(&targetRect))
- fillsBounds = false;
-
- // Apply the current clip.
- SkRect deviceClipRect;
- if (!getDeviceClipAsRect(context, deviceClipRect))
- fillsBounds = false;
- else if (!targetRect.intersect(deviceClipRect))
- return;
-
- bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap);
- bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque);
- bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
-
- if (fillsBounds && xfersOpaque)
- markRectAsOpaque(targetRect);
- else if (!preservesOpaque)
- markRectAsNonOpaque(targetRect);
-}
-
-void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType)
-{
- bool drawsOpaque = paintIsOpaque(paint, drawType, 0);
- bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
-
- if (preservesOpaque)
- return;
-
- SkRect deviceClipRect;
- getDeviceClipAsRect(context, deviceClipRect);
- markRectAsNonOpaque(deviceClipRect);
-}
-
-void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const GraphicsContext* context, const SkRect& layerOpaqueRect, const SkPaint& paint)
-{
- SkRect deviceClipRect;
- bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect);
-
- if (deviceClipRect.isEmpty())
- return;
-
- SkRect sourceOpaqueRect = layerOpaqueRect;
- // Save the opaque area in the destination, so we can preserve the parts of it under the source opaque area if possible.
- SkRect destinationOpaqueRect = currentTrackingOpaqueRect();
-
- bool outsideSourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, false);
- if (!outsideSourceOpaqueRectPreservesOpaque)
- markRectAsNonOpaque(deviceClipRect);
-
- if (!deviceClipIsARect)
- return;
- if (!sourceOpaqueRect.intersect(deviceClipRect))
- return;
-
- bool sourceOpaqueRectDrawsOpaque = paintIsOpaque(paint, FillOnly, 0);
- bool sourceOpaqueRectXfersOpaque = xfermodeIsOpaque(paint, sourceOpaqueRectDrawsOpaque);
- bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, sourceOpaqueRectDrawsOpaque);
-
- // If the layer's opaque area is being drawn opaque in the layer below, then mark it opaque. Otherwise,
- // if it preserves opaque then keep the intersection of the two.
- if (sourceOpaqueRectXfersOpaque)
- markRectAsOpaque(sourceOpaqueRect);
- else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(destinationOpaqueRect))
- markRectAsOpaque(sourceOpaqueRect);
-}
-
-void OpaqueRegionSkia::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
- // rectangle then we do that, as that is the cheapest way to increase the area returned
- // without increasing the complexity.
-
- SkRect& opaqueRect = currentTrackingOpaqueRect();
-
- if (rect.isEmpty())
- return;
- if (opaqueRect.contains(rect))
- return;
- if (rect.contains(opaqueRect)) {
- opaqueRect = rect;
- return;
- }
-
- if (rect.fTop <= opaqueRect.fTop && rect.fBottom >= opaqueRect.fBottom) {
- if (rect.fLeft < opaqueRect.fLeft && rect.fRight >= opaqueRect.fLeft)
- opaqueRect.fLeft = rect.fLeft;
- if (rect.fRight > opaqueRect.fRight && rect.fLeft <= opaqueRect.fRight)
- opaqueRect.fRight = rect.fRight;
- } else if (rect.fLeft <= opaqueRect.fLeft && rect.fRight >= opaqueRect.fRight) {
- if (rect.fTop < opaqueRect.fTop && rect.fBottom >= opaqueRect.fTop)
- opaqueRect.fTop = rect.fTop;
- if (rect.fBottom > opaqueRect.fBottom && rect.fTop <= opaqueRect.fBottom)
- opaqueRect.fBottom = rect.fBottom;
- }
-
- long opaqueArea = (long)opaqueRect.width() * (long)opaqueRect.height();
- long area = (long)rect.width() * (long)rect.height();
- if (area > opaqueArea)
- opaqueRect = rect;
-}
-
-void OpaqueRegionSkia::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|.
-
- SkRect& opaqueRect = currentTrackingOpaqueRect();
-
- if (!SkRect::Intersects(rect, opaqueRect))
- return;
- if (rect.contains(opaqueRect)) {
- markAllAsNonOpaque();
- return;
- }
-
- int deltaLeft = rect.fLeft - opaqueRect.fLeft;
- int deltaRight = opaqueRect.fRight - rect.fRight;
- int deltaTop = rect.fTop - opaqueRect.fTop;
- int deltaBottom = opaqueRect.fBottom - rect.fBottom;
-
- // horizontal is the larger of the two rectangles to the left or to the right of |rect| and inside opaqueRect.
- // vertical is the larger of the two rectangles above or below |rect| and inside opaqueRect.
- SkRect horizontal = opaqueRect;
- if (deltaTop > deltaBottom)
- horizontal.fBottom = rect.fTop;
- else
- horizontal.fTop = rect.fBottom;
- SkRect vertical = opaqueRect;
- if (deltaLeft > deltaRight)
- vertical.fRight = rect.fLeft;
- else
- vertical.fLeft = rect.fRight;
-
- if ((long)horizontal.width() * (long)horizontal.height() > (long)vertical.width() * (long)vertical.height())
- opaqueRect = horizontal;
- else
- opaqueRect = vertical;
-}
-
-void OpaqueRegionSkia::markAllAsNonOpaque()
-{
- SkRect& opaqueRect = currentTrackingOpaqueRect();
- opaqueRect.setEmpty();
-}
-
-SkRect& OpaqueRegionSkia::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;
-}
-
-} // namespace WebCore
« no previous file with comments | « Source/core/platform/graphics/skia/OpaqueRegionSkia.h ('k') | Source/core/platform/graphics/skia/SimpleFontDataSkia.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698