SkCanvas.cpp revision 90c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cb
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDevice.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h" 170017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalarCompare.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 2052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h" 21a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gLayerCounter; 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gRecCounter; 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gCanvasCounter; 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_layer() 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_layer() 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_rec() 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_rec() 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_canvas() 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_canvas() 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 472c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint; 482c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Helpers for computing fast bounds for quickReject tests 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) { 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return paint != NULL && paint->isAntiAlias() ? 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType; 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each SkDevice that the user installs. 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The clip/matrix/proc are fields that reflect the top of the save/restore 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stack. Whenever the canvas changes, it marks a dirty flag, and then before 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com these are used (assuming we're not on a layer) we rebuild these cache 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com values: they reflect the top of the save stack, but translated and clipped 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com by the device's XY offset and bitmap-bounds. 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM { 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fNext; 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* fDevice; 69045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip fClip; 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* fMatrix; 716f8f292aa768869a9e85c314b124875f57504f2creed@google.com SkPaint* fPaint; // may be null (in the future) 72f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // optional, related to canvas' external matrix 73f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix* fMVMatrix; 74f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix* fExtMatrix; 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fNext(NULL) { 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != device) { 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->ref(); 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 824b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com fDevice = device; 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 8488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com ~DeviceCM() { 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fDevice) { 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unlockPixels(); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unref(); 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com SkDELETE(fPaint); 9288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkClipStack& clipStack, SkRasterClip* updateClip) { 966f8f292aa768869a9e85c314b124875f57504f2creed@google.com int x = fDevice->getOrigin().x(); 976f8f292aa768869a9e85c314b124875f57504f2creed@google.com int y = fDevice->getOrigin().y(); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = fDevice->width(); 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = fDevice->height(); 1004b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x | y) == 0) { 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &totalMatrix; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = totalClip; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = totalMatrix; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.postTranslate(SkIntToScalar(-x), 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(-y)); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1094b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com totalClip.translate(-x, -y, &fClip); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // intersect clip, but don't translate it (yet) 1164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (updateClip) { 118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::kDifference_Op); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 122045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fClip.isEmpty()) { 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect deviceR; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com deviceR.set(0, 0, width, height); 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(deviceR.contains(fClip.getBounds())); 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 131f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // default is to assume no external matrix 132f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = NULL; 133f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = NULL; 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 135f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 136f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // can only be called after calling updateMC() 137f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) { 138f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrixStorage.setConcat(extI, *fMatrix); 139f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = &fMVMatrixStorage; 140f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas) 141f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 142f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 144f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkMatrix fMatrixStorage, fMVMatrixStorage; 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each save/restore level in the stack. 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Since a level optionally copies the matrix and/or stack, we have pointers 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for these fields. If the value is copied for this level, the copy is 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stored in the ...Storage field, and the pointer points to that. If the 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value is not copied for this level, we ignore ...Storage, and just point 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com at the corresponding value in the previous level in the stack. 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec { 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* fNext; 1570017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 1580017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec 1590017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkDrawFilter* fFilter; // the current filter (or null) 1604b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fLayer; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* If there are any layers in the stack, this points to the top-most 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com one that is at or below this level in the stack (so we know what 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap/device to draw into from this level. This value is NOT 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reference counted, since the real owner is either our fLayer field, 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com or a previous one in a lower level.) 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 16888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com DeviceCM* fTopLayer; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec(const MCRec* prev, int flags) { 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != prev) { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kMatrix_SaveFlag) { 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = *prev->fMatrix; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = prev->fMatrix; 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kClip_SaveFlag) { 1800017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClipStorage = *prev->fRasterClip; 1810017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = &fRasterClipStorage; 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1830017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = prev->fRasterClip; 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = prev->fFilter; 18782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeRef(fFilter); 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = prev->fTopLayer; 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no prev 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.reset(); 1924b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1940017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = &fRasterClipStorage; 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = NULL; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = NULL; 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayer = NULL; 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't bother initializing fNext 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_rec(); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~MCRec() { 20482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fFilter); 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fLayer); 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_rec(); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2084b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2100017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkMatrix fMatrixStorage; 2110017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip fRasterClipStorage; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw { 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2168a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 2174370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com canvas = canvas->canvasForDrawIter(); 2188a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fCanvas = canvas; 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com canvas->updateDeviceCMCache(); 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com fClipStack = &canvas->fClipStack; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = canvas->getBounder(); 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = canvas->fMCRec->fTopLayer; 2248a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fSkipEmptyClips = skipEmptyClips; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2264b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip over recs with empty clips 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fSkipEmptyClips) { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = fCurrLayer->fNext; 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 235f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com const DeviceCM* rec = fCurrLayer; 236f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com if (rec && rec->fDevice) { 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = rec->fMatrix; 239045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 240045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = &rec->fClip; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = rec->fDevice; 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fDevice->accessBitmap(true); 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = rec->fPaint; 244f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = rec->fMVMatrix; 245f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = rec->fExtMatrix; 246f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = rec->fNext; 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->setClip(fClip); 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fCurrLayer may be NULL now 253199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com 254d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack); 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* getDevice() const { return fDevice; } 2616f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getX() const { return fDevice->getOrigin().x(); } 2626f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getY() const { return fDevice->getOrigin().y(); } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& getMatrix() const { return *fMatrix; } 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& getClip() const { return *fClip; } 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* getPaint() const { return fPaint; } 2666f8f292aa768869a9e85c314b124875f57504f2creed@google.com 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* fCurrLayer; 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; // May be null. 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool8 fSkipEmptyClips; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkDraw INHERITED; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper { 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, 2818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com bool skipLayerForImageFilter = false) : fOrigPaint(paint) { 2824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fCanvas = canvas; 2834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper = paint.getLooper(); 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = canvas->getDrawFilter(); 2854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 2864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fSaveCount = canvas->getSaveCount(); 2878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fDoClearImageFilter = false; 2884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = false; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 2918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkPaint tmp; 2928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com tmp.setImageFilter(fOrigPaint.getImageFilter()); 2938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // it would be nice if we had a guess at the bounds, instead of null 2948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com (void)canvas->internalSaveLayer(NULL, &tmp, 2958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkCanvas::kARGB_ClipLayer_SaveFlag, true); 2968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // we'll clear the imageFilter for the actual draws in next(), so 2978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // it will only be applied during the restore(). 2988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fDoClearImageFilter = true; 2998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 3014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com if (fLooper) { 3024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper->init(canvas); 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 30574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com ~AutoDrawLooper() { 3078926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (fDoClearImageFilter) { 3088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fCanvas->internalRestore(); 3098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fCanvas->getSaveCount() == fSaveCount); 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 31274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com const SkPaint& paint() const { 3144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fPaint); 3154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return *fPaint; 3164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 31774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com bool next(SkDrawFilter::Type drawType); 31974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3212c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazyPaint; 3222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkCanvas* fCanvas; 3232c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint& fOrigPaint; 3242c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawLooper* fLooper; 3252c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawFilter* fFilter; 3262c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 3272c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org int fSaveCount; 3288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com bool fDoClearImageFilter; 3292c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org bool fDone; 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.combool AutoDrawLooper::next(SkDrawFilter::Type drawType) { 333632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fPaint = NULL; 3344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com if (fDone) { 3354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return false; 3364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 337632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com 3388926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (fLooper || fFilter || fDoClearImageFilter) { 339632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com SkPaint* paint = fLazyPaint.set(fOrigPaint); 3408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 3418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (fDoClearImageFilter) { 3428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint->setImageFilter(NULL); 3438926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 345632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fLooper && !fLooper->next(fCanvas, paint)) { 346632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fDone = true; 347632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com return false; 348632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 349632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fFilter) { 350632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fFilter->filter(paint, drawType); 351632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (NULL == fLooper) { 352632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com // no looper means we only draw once 353632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fDone = true; 354632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 355632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 356632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fPaint = paint; 3578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 3588926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // if we only came in here for the imagefilter, mark us as done 3598926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (!fLooper && !fFilter) { 3608926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fDone = true; 3618926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 362632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } else { 3634e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = true; 3644e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = &fOrigPaint; 3654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 3664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 367632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com // call this after any possible paint modifiers 368632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fPaint->nothingToDraw()) { 3694e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 3704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return false; 3714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 3724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return true; 3734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com} 3744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Stack helper for managing a SkBounder. In the destructor, if we were 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com given a bounder, we call its commit() method, signifying that we are 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com done accumulating bounds for that draw. 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit { 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBounderCommit() { 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fBounder) { 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->commit(); 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoValidator { 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoValidator(SkDevice* device) : fDevice(device) {} 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~AutoValidator() { 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& bm = fDevice->accessBitmap(false); 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bm.config() == SkBitmap::kARGB_4444_Config) { 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int y = 0; y < bm.height(); y++) { 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPMColor16* p = bm.getAddr16(0, y); 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = 0; x < bm.width(); x++) { 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16 c = p[x]; 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16Assert(c); 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* fDevice; 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls ////////////////// 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ 4178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ 4188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com AutoDrawLooper looper(this, paint, true); \ 4198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com while (looper.next(type)) { \ 4208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkAutoBounderCommit ac(fBounder); \ 4218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkDrawIter iter(this); 4228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 4234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_BEGIN(paint, type) \ 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ 4254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com AutoDrawLooper looper(this, paint); \ 4264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com while (looper.next(type)) { \ 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit ac(fBounder); \ 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter iter(this); 4294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 4304e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END } 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////// 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::init(SkDevice* device) { 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = NULL; 4363c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fLocalBoundsCompareType.setEmpty(); 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 4383c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fLocalBoundsCompareTypeBW.setEmpty(); 439ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 440199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = NULL; 441447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org fDeviceCMDirty = false; 442b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount = 0; 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.push_back(); 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (fMCRec) MCRec(NULL, 0); 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL)); 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = fMCRec->fLayer; 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fNext = NULL; 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4513c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fExternalMatrix.reset(); 4523c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fExternalInverse.reset(); 453f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 454f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setDevice(device); 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 458cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas() 459cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4608d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org inc_canvas(); 46174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 4628d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(NULL); 4638d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org} 4648d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(SkDevice* device) 466ea4ac97dec2eb291139bd906939e0d2e05cdd7efmike@reedtribe.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->init(device); 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap) 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 476cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref(); 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() { 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // free up the contents of our deque 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restoreToCount(1); // restore everything but the last 482b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org SkASSERT(0 == fSaveLayerCount); 4837c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); // restore the last, since we're going away 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4868d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkSafeUnref(fBounder); 487b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_canvas(); 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) { 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fBounder, bounder); 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder; 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const { 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fFilter; 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return filter; 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 507bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() { 508bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org SkDevice* device = this->getDevice(); 509bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org if (device) { 510bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org device->flush(); 511bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org } 512bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org} 513bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org 514210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.comSkISize SkCanvas::getDeviceSize() const { 515210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com SkDevice* d = this->getDevice(); 516210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 517210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com} 518210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::getDevice() const { 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 5214c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 5224c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com MCRec* rec = (MCRec*)iter.next(); 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec->fLayer->fDevice; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5270b53d59a24f667350b4282f88470713902409030reed@google.comSkDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 5280b53d59a24f667350b4282f88470713902409030reed@google.com if (updateMatrixClip) { 5290b53d59a24f667350b4282f88470713902409030reed@google.com const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 5300b53d59a24f667350b4282f88470713902409030reed@google.com } 5319266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com return fMCRec->fTopLayer->fDevice; 5329266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com} 5339266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::setDevice(SkDevice* device) { 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 5364c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 5374c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com MCRec* rec = (MCRec*)iter.next(); 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* rootDevice = rec->fLayer->fDevice; 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice == device) { 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5444b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Notify the devices that they are going in/out of scope, so they can do 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com things like lock/unlock their pixels, etc. 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device) { 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice) { 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice->unlockPixels(); 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice = device; 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 5594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Now we update our initial region to have the bounds of the new device, 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com and then intersect all of the clips in our stack with these bounds, 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com to ensure that we can't draw outside of the device's bounds (and trash 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memory). 5644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTE: this is only a partial-fix, since if the new device is larger than 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the previous one, we don't know how to "enlarge" the clips in our stack, 5674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com so drawing may be artificially restricted. Without keeping a history of 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reconstruct the correct clips, so this approximation will have to do. 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The caller really needs to restore() back to the base if they want to 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com accurately take advantage of the new device bounds. 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 57442aea289cbf801997b653a906a37a7f7e948b645reed@google.com SkIRect bounds; 57542aea289cbf801997b653a906a37a7f7e948b645reed@google.com if (device) { 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 57742aea289cbf801997b653a906a37a7f7e948b645reed@google.com } else { 57842aea289cbf801997b653a906a37a7f7e948b645reed@google.com bounds.setEmpty(); 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 58042aea289cbf801997b653a906a37a7f7e948b645reed@google.com // now jam our 1st clip to be bounds, and intersect the rest with that 58142aea289cbf801997b653a906a37a7f7e948b645reed@google.com rec->fRasterClip->setRect(bounds); 58242aea289cbf801997b653a906a37a7f7e948b645reed@google.com while ((rec = (MCRec*)iter.next()) != NULL) { 58342aea289cbf801997b653a906a37a7f7e948b645reed@google.com (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); 58442aea289cbf801997b653a906a37a7f7e948b645reed@google.com } 58542aea289cbf801997b653a906a37a7f7e948b645reed@google.com 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 589af951c9bc4cbb6e60b430194fe5127ebe99c53fbreed@google.comSkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) { 590af951c9bc4cbb6e60b430194fe5127ebe99c53fbreed@google.com SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap))); 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5956850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.combool SkCanvas::readPixels(SkBitmap* bitmap, 5966850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com int x, int y, 5976850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com Config8888 config8888) { 59851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 59951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 60051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 60151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 6026850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return device->readPixels(bitmap, x, y, config8888); 60351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 60451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 605c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 606ace7bd5623354ffabbd224d5b76550bab159c296bsalomon@google.com SkDevice* device = this->getDevice(); 60774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 608daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com SkIRect bounds; 609c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bounds.set(0, 0, device->width(), device->height()); 610daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com if (!bounds.intersect(srcRect)) { 611daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com return false; 612c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 613c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 614c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkBitmap tmp; 615c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), 616c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bounds.height()); 617c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) { 618c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bitmap->swap(tmp); 619c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return true; 620c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } else { 62151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 62251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 62351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 62451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 625d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y, 626d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com Config8888 config8888) { 62751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 62851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (device) { 629d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com device->writePixels(bitmap, x, y, config8888); 63051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 63151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 63251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 6334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() { 6344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com return this; 6354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com} 6364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 642045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& totalClip = *fMCRec->fRasterClip; 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 6444b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 64646799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 647f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 648f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 649f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 650f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 652045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip(totalClip); 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 65446799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, clip, fClipStack, &clip); 655f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 656f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 657f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 658f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 665f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, 666d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com const SkRegion& clip, 667d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com const SkClipStack& clipStack) { 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(device); 669199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com if (fLastDeviceToGainFocus != device) { 670d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com device->gainFocus(this, matrix, clip, clipStack); 671199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = device; 672199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com } 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 6794b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 6824b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 6854b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6865c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.save(); 6875c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 6885c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = canvas->getLayerDevice(i); 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 741a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 742a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SkIRect* intersection) { 743bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect clipBounds; 744bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!this->getClipDeviceBounds(&clipBounds)) { 745a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 746f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 747bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ir; 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 7504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 755bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds_affects_clip(flags)) { 7560017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fMCRec->fRasterClip->setEmpty(); 757bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 758a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7645c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); 765a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 7680017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) { 769a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 770a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org } 771a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 772a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org if (intersection) { 773a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org *intersection = ir; 774a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org } 775a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return true; 776a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org} 777a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 778a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 779a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SaveFlags flags) { 7808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return this->internalSaveLayer(bounds, paint, flags, false); 7818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com} 7828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 7838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, 7848926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SaveFlags flags, bool justForImageFilter) { 785a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org // do this before we create the layer. We don't call the public save() since 786a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org // that would invoke a possibly overridden virtual 787a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org int count = this->internalSave(flags); 788a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 789a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org fDeviceCMDirty = true; 790a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 791a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SkIRect ir; 792a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org if (!this->clipRectBounds(bounds, flags, &ir)) { 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 796b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com // Kill the imagefilter if our device doesn't allow it 797b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkLazyPaint lazyP; 798b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com if (paint && paint->getImageFilter()) { 799b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 8008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (justForImageFilter) { 8018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // early exit if the layer was just for the imageFilter 8028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return count; 8038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 804b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkPaint* p = lazyP.set(*paint); 805b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com p->setImageFilter(NULL); 806b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com paint = p; 807b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com } 808b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com } 809b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 81376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkDevice* device; 81476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com if (paint && paint->getImageFilter()) { 81576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com device = this->createCompatibleDevice(config, ir.width(), ir.height(), 81676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com isOpaque); 81776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } else { 81876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com device = this->createLayerDevice(config, ir.width(), ir.height(), 81976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com isOpaque); 82076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 821e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com if (NULL == device) { 822e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com SkDebugf("Unable to create device for layer."); 823e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com return count; 824e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com } 825e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 8266f8f292aa768869a9e85c314b124875f57504f2creed@google.com device->setOrigin(ir.fLeft, ir.fTop); 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 834b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount += 1; 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 861ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8635c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.restore(); 86488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com // reserve our layer (if any) 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 8806f8f292aa768869a9e85c314b124875f57504f2creed@google.com const SkIPoint& origin = layer->fDevice->getOrigin(); 8818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 8828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com layer->fPaint); 8838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // reset this, since internalDrawDevice will have set it to true 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8857c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 886b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org SkASSERT(fSaveLayerCount > 0); 887b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount -= 1; 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 89088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 8915c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 8925c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 90474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 905b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com int n = this->getSaveCount() - count; 906b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com for (int i = 0; i < n; ++i) { 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9117c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const { 912b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org return fSaveLayerCount > 0; 9137c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com} 9147c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) { 919a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com return bitmap.width() <= 0 || bitmap.height() <= 0 920a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#ifndef SK_ALLOW_OVER_32K_BITMAPS 921a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com || bitmap.width() > 32767 || bitmap.height() > 32767 922a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#endif 923a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com ; 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 926f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9322c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint lazy; 9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 9342c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org paint = lazy.init(); 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9362c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 93976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com#include "SkImageFilter.h" 94076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com 94176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.comclass DeviceImageFilterProxy : public SkImageFilter::Proxy { 94276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.compublic: 94376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com DeviceImageFilterProxy(SkDevice* device) : fDevice(device) {} 94474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 9458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com virtual SkDevice* createDevice(int w, int h) SK_OVERRIDE { 9468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config, 9478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com w, h, false); 9488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 9498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com virtual bool canHandleImageFilter(SkImageFilter* filter) SK_OVERRIDE { 9508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return fDevice->canHandleImageFilter(filter); 9518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 9528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com virtual bool filterImage(SkImageFilter* filter, const SkBitmap& src, 95376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com const SkMatrix& ctm, 9548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { 9558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return fDevice->filterImage(filter, src, ctm, result, offset); 9568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 9578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 95876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.comprivate: 95976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkDevice* fDevice; 96076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com}; 96176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com 9628926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y, 9638926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com const SkPaint* paint) { 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 9708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 972b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkDevice* dstDev = iter.fDevice; 97376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com paint = &looper.paint(); 97476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkImageFilter* filter = paint->getImageFilter(); 97576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 9768926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (filter && !dstDev->canHandleImageFilter(filter)) { 977b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com DeviceImageFilterProxy proxy(dstDev); 97876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkBitmap dst; 979b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com const SkBitmap& src = srcDev->accessBitmap(false); 98076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) { 9815efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com SkPaint tmpUnfiltered(*paint); 9825efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered.setImageFilter(NULL); 9835efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered); 98476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 98576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } else { 986b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 98776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 9938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com const SkPaint* paint) { 9948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkDEBUGCODE(bitmap.validate();) 9958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 9968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (reject_bitmap(bitmap)) { 9978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return; 9988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 9998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 10008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkPaint tmp; 10018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (NULL == paint) { 10028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint = &tmp; 10038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10048926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 10058926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 10068926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 10078926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com while (iter.next()) { 10088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint = &looper.paint(); 10098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkImageFilter* filter = paint->getImageFilter(); 10108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 10118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 10128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com DeviceImageFilterProxy proxy(iter.fDevice); 10138926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkBitmap dst; 10145efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com if (filter->filterImage(&proxy, bitmap, *iter.fMatrix, 10155efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com &dst, &pos)) { 10165efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com SkPaint tmpUnfiltered(*paint); 10175efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered.setImageFilter(NULL); 10185efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(), 10195efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered); 10208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } else { 10228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 10238926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_END 10268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com} 10278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1033ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1040ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1047ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1054ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1061ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1068ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 10764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1083c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 10845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 10855c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1088ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 109198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // for these simpler matrices, we can stay a rect ever after applying 109298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 109398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 109498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 10980017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevRect(r, op, doAA); 10990017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(r, op, doAA); 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 110198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // since we're rotate or some such thing, we convert the rect to a path 110298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 110398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 110498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 1108c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com return this->SkCanvas::clipPath(path, op, doAA); 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11120017708a5bcb6d0fbff0fac565085bef65de7433reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 1113c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com const SkPath& devPath, SkRegion::Op op, bool doAA) { 1114759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // base is used to limit the size (and therefore memory allocation) of the 1115759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // region that results from scan converting devPath. 1116759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com SkRegion base; 1117759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com 1118819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kIntersect_Op == op) { 1119759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // since we are intersect, we can do better (tighter) with currRgn's 1120759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // bounds, than just using the device. However, if currRgn is complex, 1121759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // our region blitter may hork, so we do that case in two steps. 11220017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (currClip->isRect()) { 11230017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->setPath(devPath, *currClip, doAA); 1124759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } else { 11250017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com base.setRect(currClip->getBounds()); 11260017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 11270017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 11280017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 1129759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } 1130819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 1131a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org const SkDevice* device = canvas->getDevice(); 1132a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org base.setRect(0, 0, device->width(), device->height()); 1133819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1134819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kReplace_Op == op) { 11350017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->setPath(devPath, base, doAA); 1136819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 11370017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 11380017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 11390017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 1140819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1141819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1142819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1143819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1144c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 11455c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 11465c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1149ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1154fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // Check if the transfomation, or the original path itself 1155fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // made us empty. Note this can also happen if we contained NaN 1156fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // values. computing the bounds detects this, and will set our 1157fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1158fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com if (devPath.getBounds().isEmpty()) { 1159fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // resetting the path will remove any NaN or other wanky values 1160fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // that might upset our scan converter. 1161fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com devPath.reset(); 1162fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com } 1163fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com 11645c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // if we called path.swap() we could avoid a deep copy of this path 11650017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevPath(devPath, op, doAA); 11665c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 11670017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 11715c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 11725c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 1175ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11775c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // todo: signal fClipStack that we have a region, and therefore (I guess) 11785c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // we have to ignore it, and use the region directly? 11795c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(rgn.getBounds()); 11805c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 11810017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(rgn, op); 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1184819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG 1185819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const { 1186819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // construct clipRgn from the clipstack 1187819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkDevice* device = this->getDevice(); 1188819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkIRect ir; 1189819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com ir.set(0, 0, device->width(), device->height()); 11900017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip tmpClip(ir); 1191819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1192819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkClipStack::B2FIter iter(fClipStack); 1193819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkClipStack::B2FIter::Clip* clip; 1194819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com while ((clip = iter.next()) != NULL) { 1195819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (clip->fPath) { 11960017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA); 1197819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else if (clip->fRect) { 1198819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com clip->fRect->round(&ir); 11990017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com tmpClip.op(ir, clip->fOp); 1200819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 12010017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com tmpClip.setEmpty(); 1202819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1203819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1204819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 12056f8f292aa768869a9e85c314b124875f57504f2creed@google.com#if 0 // enable this locally for testing 1206819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // now compare against the current rgn 1207819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkRegion& rgn = this->getTotalClip(); 12080017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkASSERT(rgn == tmpClip); 120902878b844c5cd3f17d48842da3ccf44a66621501reed@google.com#endif 1210819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1211819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif 1212819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 121390c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const { 121490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com SkClipStack::B2FIter iter(fClipStack); 121590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com const SkClipStack::B2FIter::Clip* clip; 121690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com 121790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com SkRect empty = {}; 121890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com while ((clip = iter.next()) != NULL) { 121990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com if (clip->fPath) { 122090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com visitor->clipPath(*clip->fPath, clip->fOp, clip->fDoAA); 122190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } else if (clip->fRect) { 122290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com visitor->clipRect(*clip->fRect, clip->fOp, clip->fDoAA); 122390c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } else { 122490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com visitor->clipRect(empty, SkRegion::kIntersect_Op, false); 122590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } 122690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } 122790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com} 122890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com 12295c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com/////////////////////////////////////////////////////////////////////////////// 12305c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 1231ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.comvoid SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 1233ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 1234ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeBW; 1235ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com 1236ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com if (!this->getClipBounds(&r, et)) { 1237ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.setEmpty(); 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1239ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.set(SkScalarToCompareType(r.fLeft), 1240ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fTop), 1241ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fRight), 1242ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fBottom)); 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1246d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/* current impl ignores edgetype, and relies on 1247d252db03d9650013b545ef9781fe993c07f8f314reed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 1248d252db03d9650013b545ef9781fe993c07f8f314reed@android.com antialiasing (worst case) 1249d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */ 1250ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.combool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 1251116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 12521607863b608b7db6c813228768ed5d72997bbc82reed@google.com if (!rect.isFinite()) 1253116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org return true; 1254116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 12550017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) { 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12598d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (fMCRec->fMatrix->hasPerspective()) { 1260a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 1261a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 1262a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 1263a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 12640017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); 1265a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 1266ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 1267d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 1268a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 1269a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1270a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1271a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1272a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1273a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1274a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1275a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1276a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1277a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1278a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1279a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 1284d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return path.isEmpty() || this->quickReject(path.getBounds(), et); 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1287fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.comstatic inline int pinIntForScalar(int x) { 1288fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com#ifdef SK_SCALAR_IS_FIXED 1289fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com if (x < SK_MinS16) { 1290fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com x = SK_MinS16; 1291fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com } else if (x > SK_MaxS16) { 1292fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com x = SK_MaxS16; 1293fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com } 1294fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com#endif 1295fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com return x; 1296fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com} 1297fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 1299bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ibounds; 1300bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!getClipDeviceBounds(&ibounds)) { 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1304d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 1305d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 1306d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 130772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 130872dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 130972dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1310d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1311d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1312d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 1314bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkRect r; 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // adjust it outwards if we are antialiasing 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inset = (kAA_EdgeType == et); 1317fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com 1318fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // SkRect::iset() will correctly assert if we pass a value out of range 1319fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // (when SkScalar==fixed), so we pin to legal values. This does not 1320fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // really returnt the correct answer, but its the best we can do given 1321fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // that we've promised to return SkRect (even though we support devices 1322fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // that can be larger than 32K in width or height). 1323fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com r.iset(pinIntForScalar(ibounds.fLeft - inset), 1324fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com pinIntForScalar(ibounds.fTop - inset), 1325fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com pinIntForScalar(ibounds.fRight + inset), 1326fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com pinIntForScalar(ibounds.fBottom + inset)); 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1332bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 13330017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com const SkRasterClip& clip = *fMCRec->fRasterClip; 1334bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (clip.isEmpty()) { 1335bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds) { 1336bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com bounds->setEmpty(); 1337bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1338bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return false; 1339bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1340bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 1341bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (NULL != bounds) { 1342bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com *bounds = clip.getBounds(); 1343bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1344bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return true; 1345bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1346bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1351bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const { 13520017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType; 13530017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isRect()) return kRect_ClipType; 1354bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return kComplex_ClipType; 1355bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1356bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 13580017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->forceGetBW(); 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1361f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::setExternalMatrix(const SkMatrix* matrix) { 1362f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (NULL == matrix || matrix->isIdentity()) { 1363f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 1364f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; 1365f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1366f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 1367f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 1368f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = true; 1369f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) 13704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1371f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalMatrix = *matrix; 1372fc9a3be3d2b97aba6aad27e0b9a9f105f08287b9reed@google.com if (!matrix->invert(&fExternalInverse)) { 1373fc9a3be3d2b97aba6aad27e0b9a9f105f08287b9reed@google.com fExternalInverse.reset(); 1374fc9a3be3d2b97aba6aad27e0b9a9f105f08287b9reed@google.com } 1375f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1376f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1378e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.comSkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, 1379e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com int width, int height, 1380e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com bool isOpaque) { 138188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com SkDevice* device = this->getTopDevice(); 1382cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com if (device) { 1383cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDeviceForSaveLayer(config, width, height, 1384cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com isOpaque); 1385e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1386cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return NULL; 1387e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 139074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.orgSkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, 1391e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com int width, int height, 1392e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com bool isOpaque) { 1393e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com SkDevice* device = this->getDevice(); 1394e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com if (device) { 1395cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDevice(config, width, height, isOpaque); 1396e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1397e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com return NULL; 1398e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 1399e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com} 1400e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 1401e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14062a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) { 14072a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com SkDrawIter iter(this); 14082a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com 14092a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com while (iter.next()) { 14102a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com iter.fDevice->clear(color); 14112a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com } 14122a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com} 14132a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 1415fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1416fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com} 1417fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com 1418fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) { 14194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 14224e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPaint(iter, looper.paint()); 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) 14374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 14394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 14574e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawRect(iter, r, looper.paint()); 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1464fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1465d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect storage; 1466d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 1467d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (this->quickReject(paint.computeFastBounds(bounds, &storage), 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1472fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isEmpty()) { 1473fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isInverseFillType()) { 1474fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1475fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 1476fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com return; 1477fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 14808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 14824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPath(iter, path, looper.paint()); 14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14923d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 14939efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com SkRect bounds = { 14949efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com x, y, 14959efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com x + SkIntToScalar(bitmap.width()), 14969efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com y + SkIntToScalar(bitmap.height()) 14979efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com }; 14989efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (paint) { 14999efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com (void)paint->computeFastBounds(bounds, &bounds); 15009efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com } 15019efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (this->quickReject(bounds, paint2EdgeType(paint))) { 15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 1508f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15119987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis 15129987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 15139987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 15148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 151774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this now, to avoid the cost of calling extract for RLE bitmaps 15193d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 15209efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com SkRect storage; 15219efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com const SkRect* bounds = &dst; 15229efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (paint) { 15239efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com bounds = &paint->computeFastBounds(dst, &storage); 15249efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com } 15259efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (this->quickReject(*bounds, paint2EdgeType(paint))) { 15263d60812865bb034851da777a91413ab584929887reed@google.com return; 15273d60812865bb034851da777a91413ab584929887reed@google.com } 15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15293d60812865bb034851da777a91413ab584929887reed@google.com 15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmapPtr = &bitmap; 153174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 15328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 1533878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkRect tmpSrc; 1534878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (src) { 1535878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(*src); 1536878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // if the extract process clipped off the top or left of the 1537878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // original, we adjust for that here to get the position right. 1538878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fLeft > 0) { 1539878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fRight -= tmpSrc.fLeft; 1540878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fLeft = 0; 1541fead49e3c43e67cf9648ec1999b34da959e1e36breed@android.com } 1542878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fTop > 0) { 1543878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fBottom -= tmpSrc.fTop; 1544878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fTop = 0; 1545878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } 1546878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } else { 1547878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1548878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkIntToScalar(bitmap.height())); 15498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1550878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 155174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 1552f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // ensure that src is "valid" before we pass it to our internal routines 1553f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // and to SkDevice. i.e. sure it is contained inside the original bitmap. 1554f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkIRect tmpISrc; 1555f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (src) { 1556f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); 15572ade0863c3af14d274561cc7cb6e628bb9862761reed@google.com if (!tmpISrc.intersect(*src)) { 15582ade0863c3af14d274561cc7cb6e628bb9862761reed@google.com return; 15592ade0863c3af14d274561cc7cb6e628bb9862761reed@google.com } 1560f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com src = &tmpISrc; 1561f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1562f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); 15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15659987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 15669987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 15679987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 15689987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapRect(bitmap, src, dst, paint); 15699987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 15709987ec3791336bad6af5cbe513564786b2df55aareed@google.com 15718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 15728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 1574f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1577f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 1578f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix& matrix, const SkPaint& paint) { 15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 15809b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 15814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 15829b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 15844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); 15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15869b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 15874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15909987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 15919987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkIRect& center, const SkRect& dst, 15929987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkPaint* paint) { 15933d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 159460abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com SkRect storage; 159560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com const SkRect* bounds = &dst; 159660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com if (paint) { 159760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com bounds = &paint->computeFastBounds(dst, &storage); 159860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com } 159960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com if (this->quickReject(*bounds, paint2EdgeType(paint))) { 16003d60812865bb034851da777a91413ab584929887reed@google.com return; 16013d60812865bb034851da777a91413ab584929887reed@google.com } 16023d60812865bb034851da777a91413ab584929887reed@google.com } 16033d60812865bb034851da777a91413ab584929887reed@google.com 16049987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t w = bitmap.width(); 16059987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t h = bitmap.height(); 16069987ec3791336bad6af5cbe513564786b2df55aareed@google.com 16079987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkIRect c = center; 16089987ec3791336bad6af5cbe513564786b2df55aareed@google.com // pin center to the bounds of the bitmap 16099987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fLeft = SkMax32(0, center.fLeft); 16109987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fTop = SkMax32(0, center.fTop); 16119987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fRight = SkPin32(center.fRight, c.fLeft, w); 16129987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fBottom = SkPin32(center.fBottom, c.fTop, h); 16139987ec3791336bad6af5cbe513564786b2df55aareed@google.com 16149987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t srcX[4] = { 0, c.fLeft, c.fRight, w }; 16159987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t srcY[4] = { 0, c.fTop, c.fBottom, h }; 16169987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstX[4] = { 16179987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 16189987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 16199987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 16209987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstY[4] = { 16219987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 16229987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 16239987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 162474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 16259987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstX[1] > dstX[2]) { 16269987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 16279987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[2] = dstX[1]; 16289987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 162974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 16309987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstY[1] > dstY[2]) { 16319987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 16329987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[2] = dstY[1]; 16339987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 163474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 16359987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkIRect s; 16369987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkRect d; 16379987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int y = 0; y < 3; y++) { 16389987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fTop = srcY[y]; 16399987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fBottom = srcY[y+1]; 16409987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fTop = dstY[y]; 16419987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fBottom = dstY[y+1]; 16429987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int x = 0; x < 3; x++) { 16439987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fLeft = srcX[x]; 16449987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fRight = srcX[x+1]; 16459987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fLeft = dstX[x]; 16469987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fRight = dstX[x+1]; 16479987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapRect(bitmap, &s, d, paint); 16489987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 16499987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 16509987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 16519987ec3791336bad6af5cbe513564786b2df55aareed@google.com 16529987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 16539987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 16549987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 16559987ec3791336bad6af5cbe513564786b2df55aareed@google.com 16569987ec3791336bad6af5cbe513564786b2df55aareed@google.com // Need a device entry-point, so gpu can use a mesh 16579987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapNine(bitmap, center, dst, paint); 16589987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 16599987ec3791336bad6af5cbe513564786b2df55aareed@google.com 1660f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint { 1661f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic: 1662f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { 1663f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com SkDevice::TextFlags flags; 1664f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com if (device->filterTextFlags(paint, &flags)) { 1665a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com SkPaint* newPaint = fLazy.set(paint); 1666f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setFlags(flags.fFlags); 1667f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setHinting(flags.fHinting); 1668f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = newPaint; 1669f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } else { 1670f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = &paint; 1671f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1672f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1673f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1674f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com const SkPaint& paint() const { return *fPaint; } 1675f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1676f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate: 16772c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 16782c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazy; 1679f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com}; 1680f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 168152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 168252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const SkRect& r, SkScalar textSize) { 168317b78946096265d80215a6c946286ecaa35ea7edepoger@google.com if (paint.getStyle() == SkPaint::kFill_Style) { 168452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, paint); 168552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else { 168652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint p(paint); 168717b78946096265d80215a6c946286ecaa35ea7edepoger@google.com p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 168852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, p); 168952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 169052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 169152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 169252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 169352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const char text[], size_t byteLength, 169452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar x, SkScalar y) { 169552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkASSERT(byteLength == 0 || text != NULL); 169652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 169752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com // nothing to draw 169852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (text == NULL || byteLength == 0 || 169952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fClip->isEmpty() || 170052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 170152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 170252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 170352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 170452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar width = 0; 170552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPoint start; 170652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 170752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(0, 0); // to avoid warning 170852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 170952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 171052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com width = paint.measureText(text, byteLength); 171152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 171252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offsetX = 0; 171352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 171452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = SkScalarHalf(width); 171552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 171652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = width; 171752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 171852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(x - offsetX, y); 171952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 172052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 172152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (0 == width) { 172252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 172352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 172452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 172552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com uint32_t flags = paint.getFlags(); 172652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 172752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & (SkPaint::kUnderlineText_Flag | 172852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 172952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar textSize = paint.getTextSize(); 173052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 173152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkRect r; 173252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 173352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fLeft = start.fX; 173452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fRight = start.fX + width; 173552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 173652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kUnderlineText_Flag) { 173752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 173852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 173952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 174052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 174152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 174252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 174352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kStrikeThruText_Flag) { 174452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 174552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 174652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 174752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 174852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 174952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 175052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 175152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 175252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 17554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 17568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 17584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1759f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 176052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawTextDecorations(iter, dfp.paint(), 176152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com static_cast<const char*>(text), byteLength, x, y); 17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17644e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 17688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 17694e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 17704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 17724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 17738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 1774f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 17788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 17818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 17828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 17834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 17844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 17864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 1788f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 17928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 17974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 18014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com matrix, looper.paint()); 18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 180756c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID 1808cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.comvoid SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, 1809cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkPoint pos[], const SkPaint& paint, 1810cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkPath& path, const SkMatrix* matrix) { 18114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1812cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 1813cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com while (iter.next()) { 1814cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, 18154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint(), path, matrix); 1816cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com } 1817cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 18184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 1819cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com} 1820cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com#endif 1821cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 18274e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 18284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 18314e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com colors, xmode, indices, indexCount, 18324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint()); 18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 18354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 18368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1838cb60844b34766aad4151df5e87c144d4a57e9abereed@android.comvoid SkCanvas::drawData(const void* data, size_t length) { 1839cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com // do nothing. Subclasses may do something with the data 1840cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com} 1841cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com 18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1848845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 18498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 18508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 1852845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 18530baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1858845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 1862845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 18630baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 18704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 18784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 18858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 18874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 18888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 18898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 18908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 18918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 18978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 18998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 19008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 19038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 19048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 19058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 19068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 19098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 19104b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 19128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 19148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 19158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19184b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 19198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 19208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(r); 19218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 19258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 19268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 19278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 19288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 19298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 19308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 19318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 19368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 19378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 19388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 19398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 19408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 19448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 19458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(oval, &storage), 19478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 19488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(oval); 19548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 19608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 19618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 19638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 19648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 19668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 19688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 19698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 19708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 19728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 19768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 19788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 19794b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 19808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 19818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1984f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 1985f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = save(); 19888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 19898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com restoreToCount(saveCount); 19908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 19938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 19948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 1996d642329293cce602ac24df8f585c14a98795da87reed@google.com SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 20068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 20098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 20108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::LayerIter::device() const { 20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 20178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 20188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 20218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 20228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 20238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2031