19f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 29f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com/* 39f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com * Copyright 2012 Google Inc. 49f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com * 59f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com * Use of this source code is governed by a BSD-style license that can be 69f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com * found in the LICENSE file. 79f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com */ 89f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 99f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com#include "SkBBoxHierarchyRecord.h" 109f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com#include "SkPictureStateTree.h" 119f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 120bdbea75ff1a6f3c313c18cab0139728967cb93erobertphillipsSkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size, 1319fafef9784fe7c644540ffd0ee9f6da1914a038commit-bot@chromium.org uint32_t recordFlags, 1419fafef9784fe7c644540ffd0ee9f6da1914a038commit-bot@chromium.org SkBBoxHierarchy* h) 150bdbea75ff1a6f3c313c18cab0139728967cb93erobertphillips : INHERITED(size, recordFlags) { 169f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fStateTree = SkNEW(SkPictureStateTree); 179f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fBoundingHierarchy = h; 189f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fBoundingHierarchy->ref(); 194b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org fBoundingHierarchy->setClient(this); 209f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 219f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 229f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.comvoid SkBBoxHierarchyRecord::handleBBox(const SkRect& bounds) { 234469938e92d779dff05e745559e67907bbf21e78reed@google.com SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().bytesWritten()); 24533eb782edaa0b6fece6166d3001edf72ec39f11mtklein fBoundingHierarchy->insert(draw, bounds, true); 259f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 269f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 275f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitavoid SkBBoxHierarchyRecord::willSave() { 289f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fStateTree->appendSave(); 295f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita this->INHERITED::willSave(); 309f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 319f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 32e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgSkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* bounds, 33e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org const SkPaint* paint, 34e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org SaveFlags flags) { 3568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org // For now, assume all filters affect transparent black. 3668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org // FIXME: This could be made less conservative as an optimization. 3749f085dddff10473b6ebf832a974288300224e60bsalomon bool paintAffectsTransparentBlack = paint && 3849f085dddff10473b6ebf832a974288300224e60bsalomon ((paint->getImageFilter()) || 3949f085dddff10473b6ebf832a974288300224e60bsalomon (paint->getColorFilter())); 40327f905d2cb0d37c302d651d8f2b17ea56368467dneto bool needToHandleBBox = paintAffectsTransparentBlack; 41327f905d2cb0d37c302d651d8f2b17ea56368467dneto if (!needToHandleBBox && paint) { 42327f905d2cb0d37c302d651d8f2b17ea56368467dneto // Unusual Xfermodes require us to process a saved layer 43327f905d2cb0d37c302d651d8f2b17ea56368467dneto // even with operations outisde the clip. 44327f905d2cb0d37c302d651d8f2b17ea56368467dneto // For example, DstIn is used by masking layers. 45327f905d2cb0d37c302d651d8f2b17ea56368467dneto // https://code.google.com/p/skia/issues/detail?id=1291 46327f905d2cb0d37c302d651d8f2b17ea56368467dneto SkXfermode* xfermode = paint->getXfermode(); 47327f905d2cb0d37c302d651d8f2b17ea56368467dneto SkXfermode::Mode mode; 48327f905d2cb0d37c302d651d8f2b17ea56368467dneto // SrcOver is the common case with a NULL xfermode, so we should 49327f905d2cb0d37c302d651d8f2b17ea56368467dneto // make that the fast path and bypass the mode extraction and test. 50327f905d2cb0d37c302d651d8f2b17ea56368467dneto if (xfermode && xfermode->asMode(&mode)) { 51327f905d2cb0d37c302d651d8f2b17ea56368467dneto switch (mode) { 52327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kClear_Mode: 53327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kSrc_Mode: 54327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kSrcIn_Mode: 55327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kDstIn_Mode: 56327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kSrcOut_Mode: 57327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kDstATop_Mode: 58327f905d2cb0d37c302d651d8f2b17ea56368467dneto case SkXfermode::kModulate_Mode: 59327f905d2cb0d37c302d651d8f2b17ea56368467dneto needToHandleBBox = true; 60327f905d2cb0d37c302d651d8f2b17ea56368467dneto break; 61327f905d2cb0d37c302d651d8f2b17ea56368467dneto default: 62327f905d2cb0d37c302d651d8f2b17ea56368467dneto break; 63327f905d2cb0d37c302d651d8f2b17ea56368467dneto } 64327f905d2cb0d37c302d651d8f2b17ea56368467dneto } 65327f905d2cb0d37c302d651d8f2b17ea56368467dneto } 66327f905d2cb0d37c302d651d8f2b17ea56368467dneto 6768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org SkRect drawBounds; 68327f905d2cb0d37c302d651d8f2b17ea56368467dneto if (needToHandleBBox) { 69d910f544439fffa6c2bcc5181b79b2811a4c130amtklein SkIRect deviceBounds; 70d910f544439fffa6c2bcc5181b79b2811a4c130amtklein this->getClipDeviceBounds(&deviceBounds); 71d910f544439fffa6c2bcc5181b79b2811a4c130amtklein drawBounds.set(deviceBounds); 7268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org } 734469938e92d779dff05e745559e67907bbf21e78reed@google.com fStateTree->appendSaveLayer(this->writeStream().bytesWritten()); 7468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds, paint, flags); 75327f905d2cb0d37c302d651d8f2b17ea56368467dneto if (needToHandleBBox) { 7668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org this->handleBBox(drawBounds); 7768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org this->addNoOp(); 7868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org } 7968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org return strategy; 809f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 819f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 82e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkBBoxHierarchyRecord::willRestore() { 839f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fStateTree->appendRestore(); 84e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org this->INHERITED::willRestore(); 859f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 869f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 8744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) { 889f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fStateTree->appendTransform(getTotalMatrix()); 8944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org INHERITED::didConcat(matrix); 909f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 919f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 9244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) { 939f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com fStateTree->appendTransform(getTotalMatrix()); 9444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org INHERITED::didSetMatrix(matrix); 959f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 969f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkBBoxHierarchyRecord::onClipRect(const SkRect& rect, 988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com SkRegion::Op op, 998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com ClipEdgeStyle edgeStyle) { 1004469938e92d779dff05e745559e67907bbf21e78reed@google.com fStateTree->appendClip(this->writeStream().bytesWritten()); 1018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com this->INHERITED::onClipRect(rect, op, edgeStyle); 1029f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 1039f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 1048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkBBoxHierarchyRecord::onClipRegion(const SkRegion& region, 1058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com SkRegion::Op op) { 1064469938e92d779dff05e745559e67907bbf21e78reed@google.com fStateTree->appendClip(this->writeStream().bytesWritten()); 1078f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com this->INHERITED::onClipRegion(region, op); 1089f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 1099f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 1108f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkBBoxHierarchyRecord::onClipPath(const SkPath& path, 1118f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com SkRegion::Op op, 1128f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com ClipEdgeStyle edgeStyle) { 1134469938e92d779dff05e745559e67907bbf21e78reed@google.com fStateTree->appendClip(this->writeStream().bytesWritten()); 1148f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com this->INHERITED::onClipPath(path, op, edgeStyle); 1159f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com} 1169f5898d31b91500e09a70c7f70265a2d813b2534rileya@google.com 1178f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkBBoxHierarchyRecord::onClipRRect(const SkRRect& rrect, 1188f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com SkRegion::Op op, 1198f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com ClipEdgeStyle edgeStyle) { 1204469938e92d779dff05e745559e67907bbf21e78reed@google.com fStateTree->appendClip(this->writeStream().bytesWritten()); 1218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com this->INHERITED::onClipRRect(rrect, op, edgeStyle); 122675de168d8ec37958a40a3593bd86c631d810fecjunov@chromium.org} 1234b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org 1244b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.orgbool SkBBoxHierarchyRecord::shouldRewind(void* data) { 1254b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org // SkBBoxHierarchy::rewindInserts is called by SkPicture after the 1264b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org // SkPicture has rewound its command stream. To match that rewind in the 1274b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org // BBH, we rewind all draws that reference commands that were recorded 1284b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org // past the point to which the SkPicture has rewound, which is given by 1294469938e92d779dff05e745559e67907bbf21e78reed@google.com // writeStream().bytesWritten(). 1304b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org SkPictureStateTree::Draw* draw = static_cast<SkPictureStateTree::Draw*>(data); 1314469938e92d779dff05e745559e67907bbf21e78reed@google.com return draw->fOffset >= writeStream().bytesWritten(); 1324b32bd53c63b245707822ae83e3215863303bf43commit-bot@chromium.org} 133