SkCanvas.cpp revision 819c921b0445fa9f45f18d4a560603cd9fde6ba4
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, 10246799cd9f0bded51a189d77731b25af159ab4609reed@google.com const SkClipStack& clipStack, 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 12946799cd9f0bded51a189d77731b25af159ab4609reed@google.com fDevice->setMatrixClip(*fMatrix, fClip, clipStack); 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 4804c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 4814c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@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 4884c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 4894c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@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 } 5315c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.reset(); 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute our total bounds for all devices 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 5354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now jam our 1st clip to be bounds, and intersect the rest with that 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fRegion->setRect(bounds); 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op); 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5435c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(bounds, SkRegion::kIntersect_Op); 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 548f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) { 549f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer))); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 55451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 55551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 55651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 55751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 55851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 55951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return device->readPixels(srcRect, bitmap); 56051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 56151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 5624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.comSkDeviceFactory* SkCanvas::setDeviceFactory(SkDeviceFactory* factory) { 5634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com SkDELETE(fDeviceFactory); 5644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com fDeviceFactory = factory; 5659b2135a923c8344ef4c4f52907b7ffe4fc575136reed@google.com return factory; 5664b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com} 5674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com////////////////////////////////////////////////////////////////////////////// 5694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 57051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(SkBitmap* bitmap) { 57151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 57251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 57351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 57451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 57551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkIRect bounds; 57651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com bounds.set(0, 0, device->width(), device->height()); 57751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return this->readPixels(bounds, bitmap); 57851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 57951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 58051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 58151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 58251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (device) { 58351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com device->writePixels(bitmap, x, y); 58451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 58551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 58651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getViewport(SkIPoint* size) const { 59035fc62b960db6739b19c59576085663796951e47vandebo@chromium.org if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0) 5918d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return false; 5928d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org if (size) 5938d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org size->set(getDevice()->width(), getDevice()->height()); 5948d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return true; 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::setViewport(int width, int height) { 59835fc62b960db6739b19c59576085663796951e47vandebo@chromium.org if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0) 5998d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return false; 600f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 601f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->setDevice(this->createDevice(SkBitmap::kARGB_8888_Config, width, height, 602f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com false, false))->unref(); 6038d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org return true; 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& totalClip = this->getTotalClip(); 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 6114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 61346799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 614f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 615f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 616f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 617f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion clip; 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clip = totalClip; // make a copy 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 62246799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, clip, fClipStack, &clip); 623f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 624f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 625f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 626f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 633f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, 634f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkRegion& clip) { 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(device); 636199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com if (fLastDeviceToGainFocus != device) { 637f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com device->gainFocus(this, matrix, clip); 638199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = device; 639199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com } 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 6464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 6494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 6524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6535c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.save(); 6545c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 6555c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = canvas->getLayerDevice(i); 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this before we create the layer. We don't call the public save() since 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // that would invoke a possibly overridden virtual 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = this->internalSave(flags); 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& clipBounds = this->getTotalClip().getBounds(); 718f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (clipBounds.isEmpty()) { 719f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com return count; 720f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 7244b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags)) 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fRegion->setEmpty(); 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7375c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) { 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = this->createDevice(config, ir.width(), ir.height(), 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com isOpaque, true); 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 782ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.restore(); 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reserve our layer (if any) 7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevice(layer->fDevice, layer->fX, layer->fY, 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fPaint); 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reset this, since drawDevice will have set it to true 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8085c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 8095c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fMCStack.count() > count) { 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) { 830a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com return bitmap.width() <= 0 || bitmap.height() <= 0 831a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#ifndef SK_ALLOW_OVER_32K_BITMAPS 832a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com || bitmap.width() > 32767 || bitmap.height() > 32767 833a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#endif 834a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com ; 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 837f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 845f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint); 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 847f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawDevice(SkDevice* device, int x, int y, 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8584b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *paint); 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 872ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 879ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 886ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 893ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 900ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 907ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 9154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) { 9235c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 9245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 927ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 93098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // for these simpler matrices, we can stay a rect ever after applying 93198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 93298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 93398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 9385c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(r, op); 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&ir); 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(ir, op); 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 94298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // since we're rotate or some such thing, we convert the rect to a path 94398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 94498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 94598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 94998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com return this->SkCanvas::clipPath(path, op); 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 953819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRegion* currRgn, 954819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkPath& devPath, SkRegion::Op op) { 955819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kIntersect_Op == op) { 956819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com return currRgn->setPath(devPath, *currRgn); 957819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 958819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkRegion base; 959819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkBitmap& bm = canvas->getDevice()->accessBitmap(false); 960819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com base.setRect(0, 0, bm.width(), bm.height()); 961819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 962819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kReplace_Op == op) { 963819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com return currRgn->setPath(devPath, base); 964819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 965819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkRegion rgn; 966819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com rgn.setPath(devPath, base); 967819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com return currRgn->op(rgn, op); 968819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 969819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 970819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 971819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) { 9735c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 9745c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 977ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // if we called path.swap() we could avoid a deep copy of this path 9835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevPath(devPath, op); 9845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 985819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com return clipPathHelper(this, fMCRec->fRegion, devPath, op); 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 9895c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 9905c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 993ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9955c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // todo: signal fClipStack that we have a region, and therefore (I guess) 9965c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // we have to ignore it, and use the region directly? 9975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(rgn.getBounds()); 9985c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fRegion->op(rgn, op); 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1002819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG 1003819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const { 1004819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // construct clipRgn from the clipstack 1005819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkDevice* device = this->getDevice(); 1006819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkIRect ir; 1007819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com ir.set(0, 0, device->width(), device->height()); 1008819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkRegion clipRgn(ir); 1009819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1010819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkClipStack::B2FIter iter(fClipStack); 1011819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkClipStack::B2FIter::Clip* clip; 1012819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com while ((clip = iter.next()) != NULL) { 1013819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (clip->fPath) { 1014819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com clipPathHelper(this, &clipRgn, *clip->fPath, clip->fOp); 1015819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else if (clip->fRect) { 1016819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com clip->fRect->round(&ir); 1017819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com clipRgn.op(ir, clip->fOp); 1018819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 1019819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com break; 1020819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1021819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1022819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1023819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // now compare against the current rgn 1024819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkRegion& rgn = this->getTotalClip(); 1025819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkASSERT(rgn == clipRgn); 1026819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1027819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif 1028819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 10295c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com/////////////////////////////////////////////////////////////////////////////// 10305c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 1031ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.comvoid SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 1033ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 1034ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeBW; 1035ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com 1036ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com if (!this->getClipBounds(&r, et)) { 1037ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.setEmpty(); 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1039ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.set(SkScalarToCompareType(r.fLeft), 1040ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fTop), 1041ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fRight), 1042ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fBottom)); 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1046d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/* current impl ignores edgetype, and relies on 1047d252db03d9650013b545ef9781fe993c07f8f314reed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 1048d252db03d9650013b545ef9781fe993c07f8f314reed@android.com antialiasing (worst case) 1049d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */ 1050ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.combool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 1051116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 1052116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org if (!rect.hasValidCoordinates()) 1053116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org return true; 1054116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fRegion->isEmpty()) { 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1059a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (fMCRec->fMatrix->getType() & SkMatrix::kPerspective_Mask) { 1060a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 1061a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 1062a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 1063a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 1064a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds()); 1065a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 1066ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 1067d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 1068a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 1069a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1070a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1071a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1072a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1073a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1074a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1075a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1076a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1077a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1078a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1079a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 1084d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return path.isEmpty() || this->quickReject(path.getBounds(), et); 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const { 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* current impl ignores edgetype, and relies on 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialiasing (worst case) 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fRegion->isEmpty()) { 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1097aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userT = SkScalarToCompareType(top); 1098aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userB = SkScalarToCompareType(bottom); 10994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for invalid user Y coordinates (i.e. empty) 1101d252db03d9650013b545ef9781fe993c07f8f314reed@android.com // reed: why do we need to do this check, since it slows us down? 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (userT >= userB) { 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we are above or below the local clip bounds 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); 11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return userT >= clipR.fBottom || userB <= clipR.fTop; 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& clip = *fMCRec->fRegion; 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clip.isEmpty()) { 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds) { 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds->setEmpty(); 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1120d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 1121d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 1122d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 112372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 112472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 112572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1126d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1127d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1128d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get the clip's bounds 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& ibounds = clip.getBounds(); 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // adjust it outwards if we are antialiasing 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inset = (kAA_EdgeType == et); 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ibounds.fRight + inset, ibounds.fBottom + inset); 11374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // invert into local coordinates 11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fRegion; 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1152f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::setExternalMatrix(const SkMatrix* matrix) { 1153f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (NULL == matrix || matrix->isIdentity()) { 1154f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 1155f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; 1156f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 1158f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 1159f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = true; 1160f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) 11614b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1162f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalMatrix = *matrix; 1163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com matrix->invert(&fExternalInverse); 1164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1165f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1167f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, 1168f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com bool isOpaque, bool forLayer) { 1169f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer); 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPaint_Type) 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPaint(iter, paint); 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPoint_Type) 11954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPoints(iter, mode, count, pts, paint); 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12114b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kRect_Type) 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawRect(iter, r, paint); 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 1223d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect storage; 1224d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 1225d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (this->quickReject(paint.computeFastBounds(bounds, &storage), 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPath_Type) 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPath(iter, path, paint); 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint || (paint->getMaskFilter() == NULL)) { 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect fastBounds; 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fastBounds.set(x, y, 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x + SkIntToScalar(bitmap.width()), 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y + SkIntToScalar(bitmap.height())); 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(fastBounds, paint2EdgeType(paint))) { 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 1256f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& dst, const SkPaint* paint) { 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this now, to avoid the cost of calling extract for RLE bitmaps 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(dst, paint2EdgeType(paint))) { 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmapPtr = &bitmap; 12714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 1273878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkRect tmpSrc; 1274878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (src) { 1275878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(*src); 1276878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // if the extract process clipped off the top or left of the 1277878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // original, we adjust for that here to get the position right. 1278878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fLeft > 0) { 1279878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fRight -= tmpSrc.fLeft; 1280878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fLeft = 0; 1281fead49e3c43e67cf9648ec1999b34da959e1e36breed@android.com } 1282878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fTop > 0) { 1283878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fBottom -= tmpSrc.fTop; 1284878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fTop = 0; 1285878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } 1286878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } else { 1287878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1288878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkIntToScalar(bitmap.height())); 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1290878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 1291f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1292f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // ensure that src is "valid" before we pass it to our internal routines 1293f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // and to SkDevice. i.e. sure it is contained inside the original bitmap. 1294f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkIRect tmpISrc; 1295f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (src) { 1296f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); 1297f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com tmpISrc.intersect(*src); 1298f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com src = &tmpISrc; 1299f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1300f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 1306f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1309f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 1310f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix& matrix, const SkPaint& paint) { 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 13129b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 13149b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 1316f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint); 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13189b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 13254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 13364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *paint); 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawText(iter, text, byteLength, x, y, paint); 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13584b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint); 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint); 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kText_Type) 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix, paint); 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_BEGIN(paint, SkDrawFilter::kPath_Type) 13994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com colors, xmode, indices, indexCount, paint); 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14044b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ITER_END 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1408cb60844b34766aad4151df5e87c144d4a57e9abereed@android.comvoid SkCanvas::drawData(const void* data, size_t length) { 1409cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com // do nothing. Subclasses may do something with the data 1410cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com} 1411cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1418845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 1422845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 14230baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1428845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 1432845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 14330baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 14404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 14484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 14574b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 14804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(r); 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 15148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(oval, &storage), 15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 15238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(oval); 15248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 15258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 15318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 15328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 15398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 15408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 15428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 15468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 15494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 15508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1554f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 1555f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 15568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 15578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = save(); 15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com restoreToCount(saveCount); 15608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1562f76bacff7f66724072c67edb185abf9e3add11a0reed@android.comvoid SkCanvas::drawShape(SkShape* shape) { 1563f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com // shape baseclass takes care of save/restore 1564f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com shape->draw(this); 1565f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com} 1566f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 15678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 15688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 1571d642329293cce602ac24df8f585c14a98795da87reed@google.com SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 15728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 15748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 15818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::LayerIter::device() const { 15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 15938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1607