SkCanvas.cpp revision b70ae310bbdaa1b26786773aabce5548c1f48563
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Copyright (C) 2006-2008 The Android Open Source Project 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Licensed under the Apache License, Version 2.0 (the "License"); 58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * you may not use this file except in compliance with the License. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * You may obtain a copy of the License at 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * http://www.apache.org/licenses/LICENSE-2.0 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Unless required by applicable law or agreed to in writing, software 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * distributed under the License is distributed on an "AS IS" BASIS, 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * See the License for the specific language governing permissions and 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * limitations under the License. 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDevice.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalarCompare.h" 25f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com#include "SkShape.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <new> 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gLayerCounter; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gRecCounter; 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gCanvasCounter; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_layer() 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_layer() 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_rec() 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_rec() 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_canvas() 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_canvas() 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Helpers for computing fast bounds for quickReject tests 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) { 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return paint != NULL && paint->isAntiAlias() ? 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType; 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each SkDevice that the user installs. 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The clip/matrix/proc are fields that reflect the top of the save/restore 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stack. Whenever the canvas changes, it marks a dirty flag, and then before 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com these are used (assuming we're not on a layer) we rebuild these cache 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com values: they reflect the top of the save stack, but translated and clipped 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com by the device's XY offset and bitmap-bounds. 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM { 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fNext; 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* fDevice; 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion fClip; 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* fMatrix; 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint* fPaint; // may be null (in the future) 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int16_t fX, fY; // relative to base matrix/clip 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fNext(NULL) { 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != device) { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->ref(); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = device; 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fX = SkToS16(x); 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY = SkToS16(y); 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~DeviceCM() { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fDevice) { 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unlockPixels(); 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unref(); 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fPaint); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip, 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion* updateClip) { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = fX; 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = fY; 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = fDevice->width(); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = fDevice->height(); 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x | y) == 0) { 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &totalMatrix; 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = totalClip; 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = totalMatrix; 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.postTranslate(SkIntToScalar(-x), 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(-y)); 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com totalClip.translate(-x, -y, &fClip); 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip.op(0, 0, width, height, SkRegion::kIntersect_Op); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // intersect clip, but don't translate it (yet) 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (updateClip) { 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com updateClip->op(x, y, x + width, y + height, 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::kDifference_Op); 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->setMatrixClip(*fMatrix, fClip); 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fClip.isEmpty()) { 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect deviceR; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com deviceR.set(0, 0, width, height); 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(deviceR.contains(fClip.getBounds())); 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void translateClip() { 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fX | fY) { 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip.translate(fX, fY); 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix fMatrixStorage; 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each save/restore level in the stack. 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Since a level optionally copies the matrix and/or stack, we have pointers 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for these fields. If the value is copied for this level, the copy is 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stored in the ...Storage field, and the pointer points to that. If the 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value is not copied for this level, we ignore ...Storage, and just point 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com at the corresponding value in the previous level in the stack. 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec { 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* fNext; 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion* fRegion; // points to either fRegionStorage or prev MCRec 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter* fFilter; // the current filter (or null) 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fLayer; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* If there are any layers in the stack, this points to the top-most 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com one that is at or below this level in the stack (so we know what 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap/device to draw into from this level. This value is NOT 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reference counted, since the real owner is either our fLayer field, 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com or a previous one in a lower level.) 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fTopLayer; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec(const MCRec* prev, int flags) { 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != prev) { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kMatrix_SaveFlag) { 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = *prev->fMatrix; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = prev->fMatrix; 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kClip_SaveFlag) { 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegionStorage = *prev->fRegion; 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegion = &fRegionStorage; 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegion = prev->fRegion; 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = prev->fFilter; 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter->safeRef(); 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = prev->fTopLayer; 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no prev 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.reset(); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegion = &fRegionStorage; 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = NULL; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = NULL; 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayer = NULL; 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't bother initializing fNext 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_rec(); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~MCRec() { 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter->safeUnref(); 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fLayer); 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_rec(); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix fMatrixStorage; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion fRegionStorage; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw { 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCanvas = canvas; 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com canvas->updateDeviceCMCache(); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = canvas->getBounder(); 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = canvas->fMCRec->fTopLayer; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSkipEmptyClips = skipEmptyClips; 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip over recs with empty clips 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fSkipEmptyClips) { 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = fCurrLayer->fNext; 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fCurrLayer) { 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* rec = fCurrLayer; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = rec->fMatrix; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = &rec->fClip; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = rec->fDevice; 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fDevice->accessBitmap(true); 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayerX = rec->fX; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayerY = rec->fY; 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = rec->fPaint; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = rec->fNext; 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->setClip(fClip); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fCurrLayer may be NULL now 251199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCanvas->prepareForDeviceDraw(fDevice); 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int getX() const { return fLayerX; } 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int getY() const { return fLayerY; } 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* getDevice() const { return fDevice; } 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& getMatrix() const { return *fMatrix; } 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& getClip() const { return *fClip; } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* getPaint() const { return fPaint; } 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* fCurrLayer; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; // May be null. 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fLayerX; 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fLayerY; 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool8 fSkipEmptyClips; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkDraw INHERITED; 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper { 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t) 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) { 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((fLooper = paint.getLooper()) != NULL) { 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLooper->init(canvas, (SkPaint*)&paint); 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOnce = true; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = canvas->getDrawFilter(); 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedFilterRestore = false; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~AutoDrawLooper() { 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fNeedFilterRestore) { 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fFilter); 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter->restore(fCanvas, fPaint, fType); 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fLooper) { 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLooper->restore(); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter* filter = fFilter; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we drew earlier with a filter, then we need to restore first 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fNeedFilterRestore) { 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filter); 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com filter->restore(fCanvas, fPaint, fType); 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedFilterRestore = false; 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool result; 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fLooper) { 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = fLooper->next(); 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = fOnce; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOnce = false; 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're gonna draw, give the filter a chance to do its work 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (result && NULL != filter) { 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedFilterRestore = result = filter->filter(fCanvas, fPaint, 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fType); 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawLooper* fLooper; 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter* fFilter; 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint* fPaint; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter::Type fType; 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fOnce; 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fNeedFilterRestore; 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Stack helper for managing a SkBounder. In the destructor, if we were 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com given a bounder, we call its commit() method, signifying that we are 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com done accumulating bounds for that draw. 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit { 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBounderCommit() { 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fBounder) { 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->commit(); 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoValidator { 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoValidator(SkDevice* device) : fDevice(device) {} 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~AutoValidator() { 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& bm = fDevice->accessBitmap(false); 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bm.config() == SkBitmap::kARGB_4444_Config) { 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int y = 0; y < bm.height(); y++) { 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPMColor16* p = bm.getAddr16(0, y); 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = 0; x < bm.width(); x++) { 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16 c = p[x]; 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16Assert(c); 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* fDevice; 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls ////////////////// 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define ITER_BEGIN(paint, type) \ 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoDrawLooper looper(this, paint, type); \ 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (looper.next()) { \ 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit ac(fBounder); \ 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter iter(this); 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define ITER_END } 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////// 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::init(SkDevice* device) { 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = NULL; 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 393ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 394199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = NULL; 395447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org fDeviceCMDirty = false; 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.push_back(); 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (fMCRec) MCRec(NULL, 0); 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL)); 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = fMCRec->fLayer; 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fNext = NULL; 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setDevice(device); 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4078d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.orgSkCanvas::SkCanvas(SkDeviceFactory* factory) 4088d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)), 4098d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory(factory) { 4108d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org inc_canvas(); 4118d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4128d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if (!factory) 4138d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory = SkNEW(SkRasterDeviceFactory); 4148d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4158d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(NULL); 4168d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org} 4178d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(SkDevice* device) 4198d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)), 4208d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory(device->getDeviceFactory()) { 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->init(device); 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap) 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4308d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap)); 4318d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory = device->getDeviceFactory(); 4328d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(device)->unref(); 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() { 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // free up the contents of our deque 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restoreToCount(1); // restore everything but the last 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); // restore the last, since we're going away 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4408d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkSafeUnref(fBounder); 441b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org SkDELETE(fDeviceFactory); 442b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_canvas(); 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) { 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fBounder, bounder); 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder; 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const { 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fFilter; 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return filter; 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::getDevice() const { 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDeque::Iter iter(fMCStack); 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* rec = (MCRec*)iter.next(); 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec->fLayer->fDevice; 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::setDevice(SkDevice* device) { 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDeque::Iter iter(fMCStack); 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* rec = (MCRec*)iter.next(); 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* rootDevice = rec->fLayer->fDevice; 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice == device) { 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Notify the devices that they are going in/out of scope, so they can do 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com things like lock/unlock their pixels, etc. 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device) { 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice) { 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice->unlockPixels(); 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice = device; 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Now we update our initial region to have the bounds of the new device, 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com and then intersect all of the clips in our stack with these bounds, 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com to ensure that we can't draw outside of the device's bounds (and trash 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memory). 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTE: this is only a partial-fix, since if the new device is larger than 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the previous one, we don't know how to "enlarge" the clips in our stack, 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com so drawing may be artificially restricted. Without keeping a history of 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reconstruct the correct clips, so this approximation will have to do. 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The caller really needs to restore() back to the base if they want to 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com accurately take advantage of the new device bounds. 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == device) { 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fRegion->setEmpty(); 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)rec->fRegion->setEmpty(); 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute our total bounds for all devices 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now jam our 1st clip to be bounds, and intersect the rest with that 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fRegion->setRect(bounds); 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op); 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) { 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap))); 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getViewport(SkIPoint* size) const { 5398d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if ((fDeviceFactory->getDeviceCapabilities() 5408d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org & SkDeviceFactory::kGL_Capability) == 0) 5418d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return false; 5428d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if (size) 5438d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org size->set(getDevice()->width(), getDevice()->height()); 5448d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return true; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::setViewport(int width, int height) { 5488d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if ((fDeviceFactory->getDeviceCapabilities() 5498d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org & SkDeviceFactory::kGL_Capability) == 0) 5508d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return false; 5518d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->setDevice(createDevice(SkBitmap::kARGB_8888_Config, width, height, 5528d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org false, false))->unref(); 5538d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return true; 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& totalClip = this->getTotalClip(); 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->updateMC(totalMatrix, totalClip, NULL); 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion clip; 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clip = totalClip; // make a copy 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->updateMC(totalMatrix, clip, &clip); 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::prepareForDeviceDraw(SkDevice* device) { 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(device); 577199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com if (fLastDeviceToGainFocus != device) { 578199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com device->gainFocus(this); 579199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = device; 580199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com } 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = canvas->getLayerDevice(i); 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this before we create the layer. We don't call the public save() since 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // that would invoke a possibly overridden virtual 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = this->internalSave(flags); 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& clipBounds = this->getTotalClip().getBounds(); 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags)) 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fRegion->setEmpty(); 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) { 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = this->createDevice(config, ir.width(), ir.height(), 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com isOpaque, true); 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 716ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reserve our layer (if any) 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevice(layer->fDevice, layer->fX, layer->fY, 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fPaint); 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reset this, since drawDevice will have set it to true 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fMCStack.count() > count) { 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) { 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bitmap.width() <= 0 || bitmap.height() <= 0 || 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() > 32767 || bitmap.height() > 32767; 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->commonDrawBitmap(bitmap, matrix, tmpPaint); 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->commonDrawBitmap(bitmap, matrix, *paint); 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawDevice(SkDevice* device, int x, int y, 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *paint); 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 800ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 807ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 814ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 821ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 828ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 835ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) { 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 853ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 85698de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // for these simpler matrices, we can stay a rect ever after applying 85798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 85898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 85998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&ir); 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(ir, op); 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 86798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // since we're rotate or some such thing, we convert the rect to a path 86898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 86998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 87098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 87498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com return this->SkCanvas::clipPath(path, op); 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) { 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 881ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkRegion::kIntersect_Op == op) { 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->setPath(devPath, *fMCRec->fRegion); 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion base; 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& bm = this->getDevice()->accessBitmap(false); 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base.setRect(0, 0, bm.width(), bm.height()); 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkRegion::kReplace_Op == op) { 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->setPath(devPath, base); 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion rgn; 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rgn.setPath(devPath, base); 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(rgn, op); 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 906ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(rgn, op); 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 911ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.comvoid SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 913ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 914ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeBW; 915ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com 916ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com if (!this->getClipBounds(&r, et)) { 917ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.setEmpty(); 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 919ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.set(SkScalarToCompareType(r.fLeft), 920ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fTop), 921ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fRight), 922ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fBottom)); 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 926d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/* current impl ignores edgetype, and relies on 927d252db03d9650013b545ef9781fe993c07f8f314reed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 928d252db03d9650013b545ef9781fe993c07f8f314reed@android.com antialiasing (worst case) 929d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */ 930ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.combool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fRegion->isEmpty()) { 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 935a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (fMCRec->fMatrix->getType() & SkMatrix::kPerspective_Mask) { 936a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 937a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 938a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 939a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 940a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds()); 941a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 942ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 943d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 944a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 945a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 946a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 947a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userT >= clipR.fBottom || userB <= clipR.fTop) { 948a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 949a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 950a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 951a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 952a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userL >= clipR.fRight || userR <= clipR.fLeft) { 953a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 954a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 955a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 960d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return path.isEmpty() || this->quickReject(path.getBounds(), et); 9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const { 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* current impl ignores edgetype, and relies on 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialiasing (worst case) 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fRegion->isEmpty()) { 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 973aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userT = SkScalarToCompareType(top); 974aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userB = SkScalarToCompareType(bottom); 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for invalid user Y coordinates (i.e. empty) 977d252db03d9650013b545ef9781fe993c07f8f314reed@android.com // reed: why do we need to do this check, since it slows us down? 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (userT >= userB) { 9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we are above or below the local clip bounds 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); 9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return userT >= clipR.fBottom || userB <= clipR.fTop; 9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& clip = *fMCRec->fRegion; 9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clip.isEmpty()) { 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds) { 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds->setEmpty(); 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 996d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 997d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 998d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 99972dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 100072dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 100172dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1002d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1003d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1004d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get the clip's bounds 10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& ibounds = clip.getBounds(); 10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // adjust it outwards if we are antialiasing 10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inset = (kAA_EdgeType == et); 10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ibounds.fRight + inset, ibounds.fBottom + inset); 10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // invert into local coordinates 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fRegion; 10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height, bool isOpaque, bool isForLayer) { 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10338d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return fDeviceFactory->newDevice(config, width, height, isOpaque, 10348d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org isForLayer); 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPaint_Type) 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPaint(iter, paint); 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPoint_Type) 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPoints(iter, mode, count, pts, paint); 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kRect_Type) 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawRect(iter, r, paint); 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 1088d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect storage; 1089d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 1090d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (this->quickReject(paint.computeFastBounds(bounds, &storage), 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPath_Type) 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPath(iter, path, paint); 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint || (paint->getMaskFilter() == NULL)) { 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect fastBounds; 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fastBounds.set(x, y, 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x + SkIntToScalar(bitmap.width()), 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y + SkIntToScalar(bitmap.height())); 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(fastBounds, paint2EdgeType(paint))) { 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalDrawBitmap(bitmap, matrix, paint); 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& dst, const SkPaint* paint) { 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this now, to avoid the cost of calling extract for RLE bitmaps 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(dst, paint2EdgeType(paint))) { 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap tmp; // storage if we need a subset of bitmap 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmapPtr = &bitmap; 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != src) { 11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!bitmap.extractSubset(&tmp, *src)) { 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // extraction failed 11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmapPtr = &tmp; 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 1146878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkRect tmpSrc; 1147878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (src) { 1148878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(*src); 1149878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // if the extract process clipped off the top or left of the 1150878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // original, we adjust for that here to get the position right. 1151878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fLeft > 0) { 1152878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fRight -= tmpSrc.fLeft; 1153878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fLeft = 0; 1154fead49e3c43e67cf9648ec1999b34da959e1e36breed@android.com } 1155878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fTop > 0) { 1156878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fBottom -= tmpSrc.fTop; 1157878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fTop = 0; 1158878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } 1159878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } else { 1160878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1161878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkIntToScalar(bitmap.height())); 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1163878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalDrawBitmap(*bitmapPtr, matrix, paint); 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalDrawBitmap(bitmap, matrix, paint); 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 11769b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 11789b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawBitmap(iter, bitmap, matrix, paint); 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11829b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *paint); 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawText(iter, text, byteLength, x, y, paint); 12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint); 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint); 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix, paint); 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPath_Type) 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com colors, xmode, indices, indexCount, paint); 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1272cb60844b34766aad4151df5e87c144d4a57e9abereed@android.comvoid SkCanvas::drawData(const void* data, size_t length) { 1273cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com // do nothing. Subclasses may do something with the data 1274cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com} 1275cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1282845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 1286845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 12870baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1292845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 1296845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 12970baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(r); 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(oval, &storage), 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(oval); 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1418f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 1419f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = save(); 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com restoreToCount(saveCount); 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1426f76bacff7f66724072c67edb185abf9e3add11a0reed@android.comvoid SkCanvas::drawShape(SkShape* shape) { 1427f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com // shape baseclass takes care of save/restore 1428f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com shape->draw(this); 1429f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com} 1430f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need COMPILE_TIME_ASSERT 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(sizeof(fStorage) >= sizeof(SkDrawIter)); 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::LayerIter::device() const { 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1472