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