15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2012, Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/skia/OpaqueRegionSkia.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/GraphicsContext.h"
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkCanvas.h"
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkColorFilter.h"
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkShader.h"
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)OpaqueRegionSkia::OpaqueRegionSkia()
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_opaqueRect(SkRect::MakeEmpty())
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)OpaqueRegionSkia::~OpaqueRegionSkia()
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect OpaqueRegionSkia::asRect() const
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Returns the largest enclosed rect.
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int left = SkScalarCeil(m_opaqueRect.fLeft);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int top = SkScalarCeil(m_opaqueRect.fTop);
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int right = SkScalarFloor(m_opaqueRect.fRight);
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int bottom = SkScalarFloor(m_opaqueRect.fBottom);
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return IntRect(left, top, right-left, bottom-top);
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if the xfermode will force the dst to be opaque, regardless of the current dst.
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool xfermodeIsOpaque(const SkPaint& paint, bool srcIsOpaque)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!srcIsOpaque)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkXfermode* xfermode = paint.getXfermode();
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!xfermode)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true; // default to kSrcOver_Mode
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkXfermode::Mode mode;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!xfermode->asMode(&mode))
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (mode) {
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrc_Mode: // source
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstOver_Mode: // source + dest - source*dest
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstATop_Mode: // source
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kPlus_Mode: // source+dest
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default: // the rest are all source + dest - source*dest
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kClear_Mode: // 0
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDst_Mode: // dest
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcIn_Mode: // source * dest
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstIn_Mode: // dest * source
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcOut_Mode: // source * (1-dest)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstOut_Mode: // dest * (1-source)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcATop_Mode: // dest
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if the xfermode will keep the dst opaque, assuming the dst is already opaque.
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaque)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkXfermode* xfermode = paint.getXfermode();
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!xfermode)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true; // default to kSrcOver_Mode
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkXfermode::Mode mode;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!xfermode->asMode(&mode))
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (mode) {
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDst_Mode: // dest
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstOver_Mode: // source + dest - source*dest
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcATop_Mode: // dest
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kPlus_Mode: // source+dest
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default: // the rest are all source + dest - source*dest
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kClear_Mode: // 0
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcOut_Mode: // source * (1-dest)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstOut_Mode: // dest * (1-source)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrc_Mode: // source
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kSrcIn_Mode: // source * dest
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstIn_Mode: // dest * source
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case SkXfermode::kDstATop_Mode: // source
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return srcIsOpaque;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if all pixels painted will be opaque.
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool paintIsOpaque(const SkPaint& paint, OpaqueRegionSkia::DrawType drawType, const SkBitmap* bitmap)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paint.getAlpha() < 0xFF)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool checkFillOnly = drawType != OpaqueRegionSkia::FillOrStroke;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias())
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkShader* shader = paint.getShader();
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (shader && !shader->isOpaque())
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (bitmap && !bitmap->isOpaque())
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paint.getLooper())
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paint.getImageFilter())
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paint.getMaskFilter())
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkColorFilter* colorFilter = paint.getColorFilter();
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag))
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if there is a rectangular clip, with the result in |deviceClipRect|.
15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static inline bool getDeviceClipAsRect(const GraphicsContext* context, SkRect& deviceClipRect)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Get the current clip in device coordinate space.
15581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkIRect deviceClipIRect;
15981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    if (context->canvas()->getClipDeviceBounds(&deviceClipIRect))
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        deviceClipRect.set(deviceClipIRect);
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        deviceClipRect.setEmpty();
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpaqueRegionSkia::pushCanvasLayer(const SkPaint* paint)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CanvasLayerState state;
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paint)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        state.paint = *paint;
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_canvasLayerStack.append(state);
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::popCanvasLayer(const GraphicsContext* context)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_canvasLayerStack.isEmpty());
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_canvasLayerStack.isEmpty())
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CanvasLayerState& canvasLayer = m_canvasLayerStack.last();
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect layerOpaqueRect = canvasLayer.opaqueRect;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkPaint layerPaint = canvasLayer.paint;
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Apply the image mask.
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (canvasLayer.hasImageMask && !layerOpaqueRect.intersect(canvasLayer.imageOpaqueRect))
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        layerOpaqueRect.setEmpty();
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_canvasLayerStack.removeLast();
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpaqueRegionSkia::setImageMask(const SkRect& imageOpaqueRect)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_canvasLayerStack.isEmpty());
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_canvasLayerStack.last().hasImageMask = true;
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_canvasLayerStack.last().imageOpaqueRect = imageOpaqueRect;
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::didDrawRect(const GraphicsContext* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Any stroking may put alpha in pixels even if the filling part does not.
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (paint.getStyle() != SkPaint::kFill_Style) {
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool fillsBounds = false;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!paint.canComputeFastBounds())
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            didDrawUnbounded(context, paint, FillOrStroke);
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            SkRect strokeRect;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            strokeRect = paint.computeFastBounds(fillRect, &strokeRect);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillOrStroke);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly);
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::didDrawPath(const GraphicsContext* context, const SkPath& path, const SkPaint& paint)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect rect;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (path.isRect(&rect)) {
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDrawRect(context, rect, paint, 0);
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool fillsBounds = false;
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!paint.canComputeFastBounds())
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDrawUnbounded(context, paint, FillOrStroke);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect = paint.computeFastBounds(path.getBounds(), &rect);
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke);
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::didDrawPoints(const GraphicsContext* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!numPoints)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect rect;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rect.fLeft = points[0].fX;
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rect.fRight = points[0].fX + 1;
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rect.fTop = points[0].fY;
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rect.fBottom = points[0].fY + 1;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 1; i < numPoints; ++i) {
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.fLeft = std::min(rect.fLeft, points[i].fX);
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.fRight = std::max(rect.fRight, points[i].fX + 1);
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.fTop = std::min(rect.fTop, points[i].fY);
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect.fBottom = std::max(rect.fBottom, points[i].fY + 1);
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool fillsBounds = false;
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!paint.canComputeFastBounds())
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDrawUnbounded(context, paint, FillOrStroke);
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect = paint.computeFastBounds(rect, &rect);
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke);
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::didDrawBounded(const GraphicsContext* context, const SkRect& bounds, const SkPaint& paint)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool fillsBounds = false;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!paint.canComputeFastBounds())
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDrawUnbounded(context, paint, FillOrStroke);
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkRect rect;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rect = paint.computeFastBounds(bounds, &rect);
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke);
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::didDraw(const GraphicsContext* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect targetRect = rect;
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Apply the transform to device coordinate space.
28481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    SkMatrix canvasTransform = context->canvas()->getTotalMatrix();
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!canvasTransform.mapRect(&targetRect))
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fillsBounds = false;
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Apply the current clip.
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect deviceClipRect;
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!getDeviceClipAsRect(context, deviceClipRect))
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fillsBounds = false;
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!targetRect.intersect(deviceClipRect))
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap);
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque);
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fillsBounds && xfersOpaque)
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markRectAsOpaque(targetRect);
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!preservesOpaque)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markRectAsNonOpaque(targetRect);
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool drawsOpaque = paintIsOpaque(paint, drawType, 0);
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque);
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (preservesOpaque)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect deviceClipRect;
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getDeviceClipAsRect(context, deviceClipRect);
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    markRectAsNonOpaque(deviceClipRect);
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void OpaqueRegionSkia::applyOpaqueRegionFromLayer(const GraphicsContext* context, const SkRect& layerOpaqueRect, const SkPaint& paint)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect deviceClipRect;
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect);
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (deviceClipRect.isEmpty())
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect sourceOpaqueRect = layerOpaqueRect;
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Save the opaque area in the destination, so we can preserve the parts of it under the source opaque area if possible.
328926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SkRect destinationOpaqueRect = currentTrackingOpaqueRect();
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool outsideSourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, false);
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!outsideSourceOpaqueRectPreservesOpaque)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markRectAsNonOpaque(deviceClipRect);
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!deviceClipIsARect)
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!sourceOpaqueRect.intersect(deviceClipRect))
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool sourceOpaqueRectDrawsOpaque = paintIsOpaque(paint, FillOnly, 0);
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool sourceOpaqueRectXfersOpaque = xfermodeIsOpaque(paint, sourceOpaqueRectDrawsOpaque);
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, sourceOpaqueRectDrawsOpaque);
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the layer's opaque area is being drawn opaque in the layer below, then mark it opaque. Otherwise,
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // if it preserves opaque then keep the intersection of the two.
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sourceOpaqueRectXfersOpaque)
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markRectAsOpaque(sourceOpaqueRect);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(destinationOpaqueRect))
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markRectAsOpaque(sourceOpaqueRect);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect)
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We want to keep track of an opaque region but bound its complexity at a constant size.
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We keep track of the largest rectangle seen by area. If we can add the new rect to this
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // rectangle then we do that, as that is the cheapest way to increase the area returned
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // without increasing the complexity.
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SkRect& opaqueRect = currentTrackingOpaqueRect();
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rect.isEmpty())
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (opaqueRect.contains(rect))
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rect.contains(opaqueRect)) {
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        opaqueRect = rect;
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rect.fTop <= opaqueRect.fTop && rect.fBottom >= opaqueRect.fBottom) {
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rect.fLeft < opaqueRect.fLeft && rect.fRight >= opaqueRect.fLeft)
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            opaqueRect.fLeft = rect.fLeft;
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rect.fRight > opaqueRect.fRight && rect.fLeft <= opaqueRect.fRight)
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            opaqueRect.fRight = rect.fRight;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (rect.fLeft <= opaqueRect.fLeft && rect.fRight >= opaqueRect.fRight) {
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rect.fTop < opaqueRect.fTop && rect.fBottom >= opaqueRect.fTop)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            opaqueRect.fTop = rect.fTop;
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rect.fBottom > opaqueRect.fBottom && rect.fTop <= opaqueRect.fBottom)
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            opaqueRect.fBottom = rect.fBottom;
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    long opaqueArea = (long)opaqueRect.width() * (long)opaqueRect.height();
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    long area = (long)rect.width() * (long)rect.height();
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (area > opaqueArea)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        opaqueRect = rect;
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpaqueRegionSkia::markRectAsNonOpaque(const SkRect& rect)
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We want to keep as much of the current opaque rectangle as we can, so find the one largest
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // rectangle inside m_opaqueRect that does not intersect with |rect|.
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SkRect& opaqueRect = currentTrackingOpaqueRect();
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!SkRect::Intersects(rect, opaqueRect))
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rect.contains(opaqueRect)) {
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        markAllAsNonOpaque();
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int deltaLeft = rect.fLeft - opaqueRect.fLeft;
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int deltaRight = opaqueRect.fRight - rect.fRight;
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int deltaTop = rect.fTop - opaqueRect.fTop;
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int deltaBottom = opaqueRect.fBottom - rect.fBottom;
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // horizontal is the larger of the two rectangles to the left or to the right of |rect| and inside opaqueRect.
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // vertical is the larger of the two rectangles above or below |rect| and inside opaqueRect.
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect horizontal = opaqueRect;
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (deltaTop > deltaBottom)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        horizontal.fBottom = rect.fTop;
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        horizontal.fTop = rect.fBottom;
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkRect vertical = opaqueRect;
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (deltaLeft > deltaRight)
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        vertical.fRight = rect.fLeft;
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        vertical.fLeft = rect.fRight;
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ((long)horizontal.width() * (long)horizontal.height() > (long)vertical.width() * (long)vertical.height())
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        opaqueRect = horizontal;
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        opaqueRect = vertical;
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void OpaqueRegionSkia::markAllAsNonOpaque()
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
427926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SkRect& opaqueRect = currentTrackingOpaqueRect();
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    opaqueRect.setEmpty();
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)SkRect& OpaqueRegionSkia::currentTrackingOpaqueRect()
432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // If we are drawing into a canvas layer, then track the opaque rect in that layer.
434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return m_canvasLayerStack.isEmpty() ? m_opaqueRect : m_canvasLayerStack.last().opaqueRect;
435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
438