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) 33c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "platform/graphics/RegionTracker.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h" 36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "third_party/skia/include/core/SkColorFilter.h" 37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "third_party/skia/include/core/SkShader.h" 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)RegionTracker::RegionTracker() 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_opaqueRect(SkRect::MakeEmpty()) 43c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_trackedRegionType(Opaque) 44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 46c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 47c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::reset() 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 49c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(m_canvasLayerStack.isEmpty()); 50c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_opaqueRect = SkRect::MakeEmpty(); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)IntRect RegionTracker::asRect() const 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Returns the largest enclosed rect. 5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // TODO: actually, this logic looks like its returning the smallest. 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // to return largest, shouldn't we take floor of left/top 5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // and the ceil of right/bottom? 5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int left = SkScalarCeilToInt(m_opaqueRect.fLeft); 6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int top = SkScalarCeilToInt(m_opaqueRect.fTop); 6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int right = SkScalarFloorToInt(m_opaqueRect.fRight); 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int bottom = SkScalarFloorToInt(m_opaqueRect.fBottom); 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntRect(left, top, right-left, bottom-top); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if the xfermode will force the dst to be opaque, regardless of the current dst. 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool xfermodeIsOpaque(const SkPaint& paint, bool srcIsOpaque) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!srcIsOpaque) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkXfermode* xfermode = paint.getXfermode(); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!xfermode) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; // default to kSrcOver_Mode 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkXfermode::Mode mode; 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!xfermode->asMode(&mode)) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (mode) { 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrc_Mode: // source 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcOver_Mode: // source + dest - source*dest 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstOver_Mode: // source + dest - source*dest 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstATop_Mode: // source 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kPlus_Mode: // source+dest 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: // the rest are all source + dest - source*dest 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kClear_Mode: // 0 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDst_Mode: // dest 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcIn_Mode: // source * dest 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstIn_Mode: // dest * source 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcOut_Mode: // source * (1-dest) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstOut_Mode: // dest * (1-source) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcATop_Mode: // dest 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest) 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 99c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static inline bool xfermodeIsOverwrite(const SkPaint& paint) 100c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 101c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SkXfermode* xfermode = paint.getXfermode(); 102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!xfermode) 103c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return false; // default to kSrcOver_Mode 104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SkXfermode::Mode mode; 105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!xfermode->asMode(&mode)) 106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return false; 107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) switch (mode) { 108c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) case SkXfermode::kSrc_Mode: 109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) case SkXfermode::kClear_Mode: 110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return true; 111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) default: 112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return false; 113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if the xfermode will keep the dst opaque, assuming the dst is already opaque. 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaque) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkXfermode* xfermode = paint.getXfermode(); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!xfermode) 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; // default to kSrcOver_Mode 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkXfermode::Mode mode; 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!xfermode->asMode(&mode)) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (mode) { 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDst_Mode: // dest 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcOver_Mode: // source + dest - source*dest 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstOver_Mode: // source + dest - source*dest 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcATop_Mode: // dest 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kPlus_Mode: // source+dest 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: // the rest are all source + dest - source*dest 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kClear_Mode: // 0 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcOut_Mode: // source * (1-dest) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstOut_Mode: // dest * (1-source) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest) 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrc_Mode: // source 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kSrcIn_Mode: // source * dest 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstIn_Mode: // dest * source 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SkXfermode::kDstATop_Mode: // source 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return srcIsOpaque; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if all pixels painted will be opaque. 148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static inline bool paintIsOpaque(const SkPaint& paint, RegionTracker::DrawType drawType, const SkBitmap* bitmap) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paint.getAlpha() < 0xFF) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) bool checkFillOnly = drawType != RegionTracker::FillOrStroke; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias()) 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkShader* shader = paint.getShader(); 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shader && !shader->isOpaque()) 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bitmap && !bitmap->isOpaque()) 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paint.getLooper()) 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paint.getImageFilter()) 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paint.getMaskFilter()) 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkColorFilter* colorFilter = paint.getColorFilter(); 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag)) 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if there is a rectangular clip, with the result in |deviceClipRect|. 17353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static inline bool getDeviceClipAsRect(const GraphicsContext* context, SkRect& deviceClipRect) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Get the current clip in device coordinate space. 176e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (!context->canvas()->isClipRect()) { 177e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) deviceClipRect.setEmpty(); 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 179e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkIRect deviceClipIRect; 18281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) if (context->canvas()->getClipDeviceBounds(&deviceClipIRect)) 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deviceClipRect.set(deviceClipIRect); 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deviceClipRect.setEmpty(); 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 190c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::pushCanvasLayer(const SkPaint* paint) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CanvasLayerState state; 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paint) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) state.paint = *paint; 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_canvasLayerStack.append(state); 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::popCanvasLayer(const GraphicsContext* context) 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_canvasLayerStack.isEmpty()); 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_canvasLayerStack.isEmpty()) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const CanvasLayerState& canvasLayer = m_canvasLayerStack.last(); 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect layerOpaqueRect = canvasLayer.opaqueRect; 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkPaint layerPaint = canvasLayer.paint; 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Apply the image mask. 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (canvasLayer.hasImageMask && !layerOpaqueRect.intersect(canvasLayer.imageOpaqueRect)) 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) layerOpaqueRect.setEmpty(); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_canvasLayerStack.removeLast(); 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) applyOpaqueRegionFromLayer(context, layerOpaqueRect, layerPaint); 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 217c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::setImageMask(const SkRect& imageOpaqueRect) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_canvasLayerStack.isEmpty()); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_canvasLayerStack.last().hasImageMask = true; 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_canvasLayerStack.last().imageOpaqueRect = imageOpaqueRect; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 224c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::didDrawRect(const GraphicsContext* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* sourceBitmap) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Any stroking may put alpha in pixels even if the filling part does not. 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paint.getStyle() != SkPaint::kFill_Style) { 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool fillsBounds = false; 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 230c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!paint.canComputeFastBounds()) { 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDrawUnbounded(context, paint, FillOrStroke); 232c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else { 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect strokeRect; 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) strokeRect = paint.computeFastBounds(fillRect, &strokeRect); 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDraw(context, strokeRect, paint, sourceBitmap, fillsBounds, FillOrStroke); 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style; 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDraw(context, fillRect, paint, sourceBitmap, fillsBounds, FillOnly); 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 243c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::didDrawPath(const GraphicsContext* context, const SkPath& path, const SkPaint& paint) 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect rect; 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (path.isRect(&rect)) { 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDrawRect(context, rect, paint, 0); 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool fillsBounds = false; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 253c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!paint.canComputeFastBounds()) { 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDrawUnbounded(context, paint, FillOrStroke); 255c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else { 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect = paint.computeFastBounds(path.getBounds(), &rect); 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 261c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::didDrawPoints(const GraphicsContext* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!numPoints) 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect rect; 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fLeft = points[0].fX; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fRight = points[0].fX + 1; 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fTop = points[0].fY; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fBottom = points[0].fY + 1; 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 1; i < numPoints; ++i) { 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fLeft = std::min(rect.fLeft, points[i].fX); 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fRight = std::max(rect.fRight, points[i].fX + 1); 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fTop = std::min(rect.fTop, points[i].fY); 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect.fBottom = std::max(rect.fBottom, points[i].fY + 1); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool fillsBounds = false; 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 281c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!paint.canComputeFastBounds()) { 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDrawUnbounded(context, paint, FillOrStroke); 283c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else { 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect = paint.computeFastBounds(rect, &rect); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 289c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::didDrawBounded(const GraphicsContext* context, const SkRect& bounds, const SkPaint& paint) 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool fillsBounds = false; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 293c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!paint.canComputeFastBounds()) { 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDrawUnbounded(context, paint, FillOrStroke); 295c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else { 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect rect; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rect = paint.computeFastBounds(bounds, &rect); 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didDraw(context, rect, paint, 0, fillsBounds, FillOrStroke); 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 302c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::didDraw(const GraphicsContext* context, const SkRect& rect, const SkPaint& paint, const SkBitmap* sourceBitmap, bool fillsBounds, DrawType drawType) 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect targetRect = rect; 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Apply the transform to device coordinate space. 30781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) SkMatrix canvasTransform = context->canvas()->getTotalMatrix(); 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!canvasTransform.mapRect(&targetRect)) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fillsBounds = false; 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Apply the current clip. 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect deviceClipRect; 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!getDeviceClipAsRect(context, deviceClipRect)) 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fillsBounds = false; 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (!targetRect.intersect(deviceClipRect)) 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 318c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_trackedRegionType == Overwrite && fillsBounds && xfermodeIsOverwrite(paint)) { 319c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) markRectAsOpaque(targetRect); 320c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return; 321c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 322c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawsOpaque = paintIsOpaque(paint, drawType, sourceBitmap); 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool xfersOpaque = xfermodeIsOpaque(paint, drawsOpaque); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 326c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (fillsBounds && xfersOpaque) { 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markRectAsOpaque(targetRect); 328c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else if (m_trackedRegionType == Opaque && !xfermodePreservesOpaque(paint, drawsOpaque)) { 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markRectAsNonOpaque(targetRect); 330c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 333c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::didDrawUnbounded(const GraphicsContext* context, const SkPaint& paint, DrawType drawType) 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawsOpaque = paintIsOpaque(paint, drawType, 0); 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool preservesOpaque = xfermodePreservesOpaque(paint, drawsOpaque); 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (preservesOpaque) 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect deviceClipRect; 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getDeviceClipAsRect(context, deviceClipRect); 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markRectAsNonOpaque(deviceClipRect); 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 346c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::applyOpaqueRegionFromLayer(const GraphicsContext* context, const SkRect& layerOpaqueRect, const SkPaint& paint) 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect deviceClipRect; 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool deviceClipIsARect = getDeviceClipAsRect(context, deviceClipRect); 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 351e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (deviceClipIsARect && deviceClipRect.isEmpty()) 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect sourceOpaqueRect = layerOpaqueRect; 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Save the opaque area in the destination, so we can preserve the parts of it under the source opaque area if possible. 356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) SkRect destinationOpaqueRect = currentTrackingOpaqueRect(); 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool outsideSourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, false); 359e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (!outsideSourceOpaqueRectPreservesOpaque) { 360e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (!deviceClipIsARect) { 361e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) markAllAsNonOpaque(); 362e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) return; 363e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markRectAsNonOpaque(deviceClipRect); 365e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!deviceClipIsARect) 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sourceOpaqueRect.intersect(deviceClipRect)) 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool sourceOpaqueRectDrawsOpaque = paintIsOpaque(paint, FillOnly, 0); 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool sourceOpaqueRectXfersOpaque = xfermodeIsOpaque(paint, sourceOpaqueRectDrawsOpaque); 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool sourceOpaqueRectPreservesOpaque = xfermodePreservesOpaque(paint, sourceOpaqueRectDrawsOpaque); 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the layer's opaque area is being drawn opaque in the layer below, then mark it opaque. Otherwise, 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // if it preserves opaque then keep the intersection of the two. 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sourceOpaqueRectXfersOpaque) 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markRectAsOpaque(sourceOpaqueRect); 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (sourceOpaqueRectPreservesOpaque && sourceOpaqueRect.intersect(destinationOpaqueRect)) 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markRectAsOpaque(sourceOpaqueRect); 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 384c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::markRectAsOpaque(const SkRect& rect) 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We want to keep track of an opaque region but bound its complexity at a constant size. 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We keep track of the largest rectangle seen by area. If we can add the new rect to this 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // rectangle then we do that, as that is the cheapest way to increase the area returned 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // without increasing the complexity. 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 391926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) SkRect& opaqueRect = currentTrackingOpaqueRect(); 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.isEmpty()) 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (opaqueRect.contains(rect)) 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.contains(opaqueRect)) { 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect = rect; 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.fTop <= opaqueRect.fTop && rect.fBottom >= opaqueRect.fBottom) { 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.fLeft < opaqueRect.fLeft && rect.fRight >= opaqueRect.fLeft) 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect.fLeft = rect.fLeft; 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.fRight > opaqueRect.fRight && rect.fLeft <= opaqueRect.fRight) 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect.fRight = rect.fRight; 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (rect.fLeft <= opaqueRect.fLeft && rect.fRight >= opaqueRect.fRight) { 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.fTop < opaqueRect.fTop && rect.fBottom >= opaqueRect.fTop) 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect.fTop = rect.fTop; 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.fBottom > opaqueRect.fBottom && rect.fTop <= opaqueRect.fBottom) 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect.fBottom = rect.fBottom; 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) long opaqueArea = (long)opaqueRect.width() * (long)opaqueRect.height(); 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) long area = (long)rect.width() * (long)rect.height(); 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (area > opaqueArea) 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect = rect; 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 420c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::markRectAsNonOpaque(const SkRect& rect) 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We want to keep as much of the current opaque rectangle as we can, so find the one largest 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // rectangle inside m_opaqueRect that does not intersect with |rect|. 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) SkRect& opaqueRect = currentTrackingOpaqueRect(); 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!SkRect::Intersects(rect, opaqueRect)) 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.contains(opaqueRect)) { 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) markAllAsNonOpaque(); 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int deltaLeft = rect.fLeft - opaqueRect.fLeft; 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int deltaRight = opaqueRect.fRight - rect.fRight; 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int deltaTop = rect.fTop - opaqueRect.fTop; 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int deltaBottom = opaqueRect.fBottom - rect.fBottom; 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // horizontal is the larger of the two rectangles to the left or to the right of |rect| and inside opaqueRect. 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // vertical is the larger of the two rectangles above or below |rect| and inside opaqueRect. 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect horizontal = opaqueRect; 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (deltaTop > deltaBottom) 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) horizontal.fBottom = rect.fTop; 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) horizontal.fTop = rect.fBottom; 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SkRect vertical = opaqueRect; 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (deltaLeft > deltaRight) 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) vertical.fRight = rect.fLeft; 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) vertical.fLeft = rect.fRight; 4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((long)horizontal.width() * (long)horizontal.height() > (long)vertical.width() * (long)vertical.height()) 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect = horizontal; 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect = vertical; 4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 458c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void RegionTracker::markAllAsNonOpaque() 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) SkRect& opaqueRect = currentTrackingOpaqueRect(); 4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) opaqueRect.setEmpty(); 4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 464c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)SkRect& RegionTracker::currentTrackingOpaqueRect() 465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // If we are drawing into a canvas layer, then track the opaque rect in that layer. 467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return m_canvasLayerStack.isEmpty() ? m_opaqueRect : m_canvasLayerStack.last().opaqueRect; 468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 470c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 471