SkCanvas.cpp revision 116b2bcd2c4c4d4670c7b7e2ea597414713c37fb
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 77f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // optional, related to canvas' external matrix 78f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix* fMVMatrix; 79f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix* fExtMatrix; 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fNext(NULL) { 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != device) { 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->ref(); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com fDevice = device; 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fX = SkToS16(x); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY = SkToS16(y); 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~DeviceCM() { 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fDevice) { 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unlockPixels(); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unref(); 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fPaint); 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1004b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip, 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion* updateClip) { 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = fX; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = fY; 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = fDevice->width(); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = fDevice->height(); 1074b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x | y) == 0) { 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &totalMatrix; 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = totalClip; 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = totalMatrix; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.postTranslate(SkIntToScalar(-x), 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(-y)); 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com totalClip.translate(-x, -y, &fClip); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip.op(0, 0, width, height, SkRegion::kIntersect_Op); 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // intersect clip, but don't translate it (yet) 1234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (updateClip) { 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com updateClip->op(x, y, x + width, y + height, 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::kDifference_Op); 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->setMatrixClip(*fMatrix, fClip); 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fClip.isEmpty()) { 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect deviceR; 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com deviceR.set(0, 0, width, height); 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(deviceR.contains(fClip.getBounds())); 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 138f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // default is to assume no external matrix 139f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = NULL; 140f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = NULL; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 142f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 143f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // can only be called after calling updateMC() 144f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) { 145f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrixStorage.setConcat(extI, *fMatrix); 146f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = &fMVMatrixStorage; 147f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas) 148f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 149f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void translateClip() { 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fX | fY) { 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip.translate(fX, fY); 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkMatrix fMatrixStorage, fMVMatrixStorage; 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each save/restore level in the stack. 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Since a level optionally copies the matrix and/or stack, we have pointers 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for these fields. If the value is copied for this level, the copy is 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stored in the ...Storage field, and the pointer points to that. If the 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value is not copied for this level, we ignore ...Storage, and just point 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com at the corresponding value in the previous level in the stack. 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec { 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* fNext; 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion* fRegion; // points to either fRegionStorage or prev MCRec 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter* fFilter; // the current filter (or null) 1734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fLayer; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* If there are any layers in the stack, this points to the top-most 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com one that is at or below this level in the stack (so we know what 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap/device to draw into from this level. This value is NOT 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reference counted, since the real owner is either our fLayer field, 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com or a previous one in a lower level.) 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fTopLayer; 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec(const MCRec* prev, int flags) { 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != prev) { 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kMatrix_SaveFlag) { 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = *prev->fMatrix; 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = prev->fMatrix; 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kClip_SaveFlag) { 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegionStorage = *prev->fRegion; 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegion = &fRegionStorage; 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegion = prev->fRegion; 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = prev->fFilter; 20082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeRef(fFilter); 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = prev->fTopLayer; 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no prev 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.reset(); 2054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRegion = &fRegionStorage; 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = NULL; 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = NULL; 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayer = NULL; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't bother initializing fNext 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_rec(); 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~MCRec() { 21782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fFilter); 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fLayer); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_rec(); 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix fMatrixStorage; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion fRegionStorage; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw { 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCanvas = canvas; 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com canvas->updateDeviceCMCache(); 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = canvas->getBounder(); 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = canvas->fMCRec->fTopLayer; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSkipEmptyClips = skipEmptyClips; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip over recs with empty clips 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fSkipEmptyClips) { 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = fCurrLayer->fNext; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fCurrLayer) { 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* rec = fCurrLayer; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = rec->fMatrix; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = &rec->fClip; 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = rec->fDevice; 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fDevice->accessBitmap(true); 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayerX = rec->fX; 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayerY = rec->fY; 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = rec->fPaint; 256f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = rec->fMVMatrix; 257f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = rec->fExtMatrix; 258f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = rec->fNext; 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->setClip(fClip); 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fCurrLayer may be NULL now 265199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com 266f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip); 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int getX() const { return fLayerX; } 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int getY() const { return fLayerY; } 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* getDevice() const { return fDevice; } 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& getMatrix() const { return *fMatrix; } 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& getClip() const { return *fClip; } 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* getPaint() const { return fPaint; } 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* fCurrLayer; 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; // May be null. 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fLayerX; 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fLayerY; 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool8 fSkipEmptyClips; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkDraw INHERITED; 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper { 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t) 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) { 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((fLooper = paint.getLooper()) != NULL) { 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLooper->init(canvas, (SkPaint*)&paint); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOnce = true; 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = canvas->getDrawFilter(); 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedFilterRestore = false; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~AutoDrawLooper() { 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fNeedFilterRestore) { 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fFilter); 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter->restore(fCanvas, fPaint, fType); 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fLooper) { 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLooper->restore(); 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3134b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter* filter = fFilter; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we drew earlier with a filter, then we need to restore first 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fNeedFilterRestore) { 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filter); 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com filter->restore(fCanvas, fPaint, fType); 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedFilterRestore = false; 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool result; 3254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fLooper) { 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = fLooper->next(); 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = fOnce; 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOnce = false; 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're gonna draw, give the filter a chance to do its work 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (result && NULL != filter) { 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedFilterRestore = result = filter->filter(fCanvas, fPaint, 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fType); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawLooper* fLooper; 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter* fFilter; 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint* fPaint; 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawFilter::Type fType; 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fOnce; 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fNeedFilterRestore; 3494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Stack helper for managing a SkBounder. In the destructor, if we were 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com given a bounder, we call its commit() method, signifying that we are 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com done accumulating bounds for that draw. 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit { 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBounderCommit() { 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fBounder) { 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->commit(); 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoValidator { 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoValidator(SkDevice* device) : fDevice(device) {} 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~AutoValidator() { 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& bm = fDevice->accessBitmap(false); 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bm.config() == SkBitmap::kARGB_4444_Config) { 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int y = 0; y < bm.height(); y++) { 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPMColor16* p = bm.getAddr16(0, y); 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = 0; x < bm.width(); x++) { 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16 c = p[x]; 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16Assert(c); 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* fDevice; 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls ////////////////// 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define ITER_BEGIN(paint, type) \ 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoDrawLooper looper(this, paint, type); \ 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (looper.next()) { \ 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit ac(fBounder); \ 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter iter(this); 3994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define ITER_END } 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////// 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::init(SkDevice* device) { 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = NULL; 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 407ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 408199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = NULL; 409447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org fDeviceCMDirty = false; 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.push_back(); 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (fMCRec) MCRec(NULL, 0); 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL)); 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = fMCRec->fLayer; 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fNext = NULL; 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 419f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setDevice(device); 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4238d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.orgSkCanvas::SkCanvas(SkDeviceFactory* factory) 4248d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)), 4258d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory(factory) { 4268d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org inc_canvas(); 4278d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4288d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if (!factory) 4298d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory = SkNEW(SkRasterDeviceFactory); 4308d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4318d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(NULL); 4328d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org} 4338d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(SkDevice* device) 4358d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)), 4368d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory(device->getDeviceFactory()) { 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->init(device); 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap) 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 446f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false)); 4478d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org fDeviceFactory = device->getDeviceFactory(); 4488d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(device)->unref(); 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() { 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // free up the contents of our deque 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restoreToCount(1); // restore everything but the last 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); // restore the last, since we're going away 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4568d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkSafeUnref(fBounder); 457b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org SkDELETE(fDeviceFactory); 458b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_canvas(); 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) { 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fBounder, bounder); 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder; 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const { 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fFilter; 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return filter; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::getDevice() const { 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDeque::Iter iter(fMCStack); 4814b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com MCRec* rec = (MCRec*)iter.next(); 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec->fLayer->fDevice; 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::setDevice(SkDevice* device) { 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDeque::Iter iter(fMCStack); 4894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com MCRec* rec = (MCRec*)iter.next(); 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* rootDevice = rec->fLayer->fDevice; 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice == device) { 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Notify the devices that they are going in/out of scope, so they can do 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com things like lock/unlock their pixels, etc. 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device) { 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice) { 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice->unlockPixels(); 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice = device; 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 5114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Now we update our initial region to have the bounds of the new device, 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com and then intersect all of the clips in our stack with these bounds, 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com to ensure that we can't draw outside of the device's bounds (and trash 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memory). 5164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTE: this is only a partial-fix, since if the new device is larger than 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the previous one, we don't know how to "enlarge" the clips in our stack, 5194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com so drawing may be artificially restricted. Without keeping a history of 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reconstruct the correct clips, so this approximation will have to do. 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The caller really needs to restore() back to the base if they want to 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com accurately take advantage of the new device bounds. 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == device) { 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fRegion->setEmpty(); 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)rec->fRegion->setEmpty(); 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute our total bounds for all devices 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 5344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now jam our 1st clip to be bounds, and intersect the rest with that 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fRegion->setRect(bounds); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op); 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 546f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) { 547f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer))); 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 55251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 55351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 55451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 55551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 55651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 55751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return device->readPixels(srcRect, bitmap); 55851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 55951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 5604b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.comSkDeviceFactory* SkCanvas::setDeviceFactory(SkDeviceFactory* factory) { 5614b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com SkDELETE(fDeviceFactory); 5624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com fDeviceFactory = factory; 5639b2135a923c8344ef4c4f52907b7ffe4fc575136reed@google.com return factory; 5644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com} 5654b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5664b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com////////////////////////////////////////////////////////////////////////////// 5674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 56851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(SkBitmap* bitmap) { 56951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 57051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 57151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 57251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 57351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkIRect bounds; 57451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com bounds.set(0, 0, device->width(), device->height()); 57551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return this->readPixels(bounds, bitmap); 57651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 57751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 57851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 57951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 58051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (device) { 58151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com device->writePixels(bitmap, x, y); 58251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 58351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 58451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getViewport(SkIPoint* size) const { 58835fc62b960db6739b19c59576085663796951e47vandebo@chromium.org if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0) 5898d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return false; 5908d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if (size) 5918d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org size->set(getDevice()->width(), getDevice()->height()); 5928d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return true; 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::setViewport(int width, int height) { 59635fc62b960db6739b19c59576085663796951e47vandebo@chromium.org if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0) 5978d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return false; 598f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 599f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->setDevice(this->createDevice(SkBitmap::kARGB_8888_Config, width, height, 600f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com false, false))->unref(); 6018d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return true; 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& totalClip = this->getTotalClip(); 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 6094b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->updateMC(totalMatrix, totalClip, NULL); 612f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 613f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 614f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 615f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion clip; 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clip = totalClip; // make a copy 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->updateMC(totalMatrix, clip, &clip); 621f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 622f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 623f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 624f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 631f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, 632f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkRegion& clip) { 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(device); 634199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com if (fLastDeviceToGainFocus != device) { 635f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com device->gainFocus(this, matrix, clip); 636199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = device; 637199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com } 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 6444b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 6474b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 6504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = canvas->getLayerDevice(i); 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this before we create the layer. We don't call the public save() since 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // that would invoke a possibly overridden virtual 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = this->internalSave(flags); 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& clipBounds = this->getTotalClip().getBounds(); 713f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (clipBounds.isEmpty()) { 714f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com return count; 715f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 7194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags)) 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fRegion->setEmpty(); 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) { 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = this->createDevice(config, ir.width(), ir.height(), 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com isOpaque, true); 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 776ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reserve our layer (if any) 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevice(layer->fDevice, layer->fX, layer->fY, 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fPaint); 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reset this, since drawDevice will have set it to true 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fMCStack.count() > count) { 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) { 821a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com return bitmap.width() <= 0 || bitmap.height() <= 0 822a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#ifndef SK_ALLOW_OVER_32K_BITMAPS 823a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com || bitmap.width() > 32767 || bitmap.height() > 32767 824a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#endif 825a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com ; 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 828f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 836f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint); 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 838f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawDevice(SkDevice* device, int x, int y, 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *paint); 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 863ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 870ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 877ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 884ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 891ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 898ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 9064b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) { 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 916ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 91998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // for these simpler matrices, we can stay a rect ever after applying 92098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 92198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 92298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&ir); 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(ir, op); 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 93098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // since we're rotate or some such thing, we convert the rect to a path 93198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 93298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 93398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 93798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com return this->SkCanvas::clipPath(path, op); 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) { 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 944ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkRegion::kIntersect_Op == op) { 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->setPath(devPath, *fMCRec->fRegion); 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion base; 9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& bm = this->getDevice()->accessBitmap(false); 9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base.setRect(0, 0, bm.width(), bm.height()); 9554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkRegion::kReplace_Op == op) { 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->setPath(devPath, base); 9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion rgn; 9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rgn.setPath(devPath, base); 9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(rgn, op); 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 969ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(rgn, op); 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 974ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.comvoid SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 976ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 977ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeBW; 978ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com 979ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com if (!this->getClipBounds(&r, et)) { 980ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.setEmpty(); 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 982ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.set(SkScalarToCompareType(r.fLeft), 983ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fTop), 984ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fRight), 985ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fBottom)); 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 989d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/* current impl ignores edgetype, and relies on 990d252db03d9650013b545ef9781fe993c07f8f314reed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 991d252db03d9650013b545ef9781fe993c07f8f314reed@android.com antialiasing (worst case) 992d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */ 993ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.combool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 994116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 995116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org if (!rect.hasValidCoordinates()) 996116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org return true; 997116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fRegion->isEmpty()) { 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1002a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (fMCRec->fMatrix->getType() & SkMatrix::kPerspective_Mask) { 1003a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 1004a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 1005a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 1006a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 1007a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds()); 1008a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 1009ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 1010d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 1011a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 1012a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1013a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1014a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1015a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1016a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1017a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1018a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1019a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1020a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1021a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1022a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 1027d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return path.isEmpty() || this->quickReject(path.getBounds(), et); 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const { 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* current impl ignores edgetype, and relies on 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialiasing (worst case) 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fRegion->isEmpty()) { 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1040aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userT = SkScalarToCompareType(top); 1041aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userB = SkScalarToCompareType(bottom); 10424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for invalid user Y coordinates (i.e. empty) 1044d252db03d9650013b545ef9781fe993c07f8f314reed@android.com // reed: why do we need to do this check, since it slows us down? 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (userT >= userB) { 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we are above or below the local clip bounds 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return userT >= clipR.fBottom || userB <= clipR.fTop; 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& clip = *fMCRec->fRegion; 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clip.isEmpty()) { 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds) { 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds->setEmpty(); 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1063d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 1064d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 1065d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 106672dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 106772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 106872dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1069d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1070d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1071d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get the clip's bounds 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& ibounds = clip.getBounds(); 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // adjust it outwards if we are antialiasing 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inset = (kAA_EdgeType == et); 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ibounds.fRight + inset, ibounds.fBottom + inset); 10804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // invert into local coordinates 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fRegion; 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1095f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::setExternalMatrix(const SkMatrix* matrix) { 1096f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (NULL == matrix || matrix->isIdentity()) { 1097f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 1098f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; 1099f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1100f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 1101f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 1102f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = true; 1103f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) 11044b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1105f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalMatrix = *matrix; 1106f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com matrix->invert(&fExternalInverse); 1107f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1108f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1110f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, 1111f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com bool isOpaque, bool forLayer) { 1112f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer); 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPaint_Type) 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPaint(iter, paint); 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPoint_Type) 11384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPoints(iter, mode, count, pts, paint); 11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11544b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kRect_Type) 11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawRect(iter, r, paint); 11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 1166d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect storage; 1167d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 1168d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (this->quickReject(paint.computeFastBounds(bounds, &storage), 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPath_Type) 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPath(iter, path, paint); 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint || (paint->getMaskFilter() == NULL)) { 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect fastBounds; 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fastBounds.set(x, y, 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x + SkIntToScalar(bitmap.width()), 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y + SkIntToScalar(bitmap.height())); 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(fastBounds, paint2EdgeType(paint))) { 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 1199f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& dst, const SkPaint* paint) { 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12074b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this now, to avoid the cost of calling extract for RLE bitmaps 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(dst, paint2EdgeType(paint))) { 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12124b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmapPtr = &bitmap; 12144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 1216878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkRect tmpSrc; 1217878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (src) { 1218878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(*src); 1219878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // if the extract process clipped off the top or left of the 1220878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // original, we adjust for that here to get the position right. 1221878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fLeft > 0) { 1222878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fRight -= tmpSrc.fLeft; 1223878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fLeft = 0; 1224fead49e3c43e67cf9648ec1999b34da959e1e36breed@android.com } 1225878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fTop > 0) { 1226878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fBottom -= tmpSrc.fTop; 1227878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fTop = 0; 1228878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } 1229878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } else { 1230878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1231878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkIntToScalar(bitmap.height())); 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1233878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 1234f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1235f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // ensure that src is "valid" before we pass it to our internal routines 1236f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // and to SkDevice. i.e. sure it is contained inside the original bitmap. 1237f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkIRect tmpISrc; 1238f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (src) { 1239f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); 1240f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com tmpISrc.intersect(*src); 1241f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com src = &tmpISrc; 1242f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1243f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 1249f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1252f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 1253f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix& matrix, const SkPaint& paint) { 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 12559b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 12579b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 1259f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint); 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12619b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 12684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12724b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12774b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 12794b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *paint); 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawText(iter, text, byteLength, x, y, paint); 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13014b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint); 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13064b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint); 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix, paint); 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPath_Type) 13424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com colors, xmode, indices, indexCount, paint); 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13474b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1351cb60844b34766aad4151df5e87c144d4a57e9abereed@android.comvoid SkCanvas::drawData(const void* data, size_t length) { 1352cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com // do nothing. Subclasses may do something with the data 1353cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com} 1354cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1361845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 1365845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 13660baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1371845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 1375845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 13760baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 13834b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 13914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 14004b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 14234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14314b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(r); 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(oval, &storage), 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(oval); 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 14818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14924b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1497f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 1498f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = save(); 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com restoreToCount(saveCount); 15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1505f76bacff7f66724072c67edb185abf9e3add11a0reed@android.comvoid SkCanvas::drawShape(SkShape* shape) { 1506f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com // shape baseclass takes care of save/restore 1507f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com shape->draw(this); 1508f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com} 1509f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 1514d642329293cce602ac24df8f585c14a98795da87reed@google.com SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 15208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 15238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 15248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::LayerIter::device() const { 15318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 15328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 15398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 15408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 15418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 15428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 15448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 15498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1550