SkCanvas.cpp revision 0017708a5bcb6d0fbff0fac565085bef65de7433
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; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion 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 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip, 9546799cd9f0bded51a189d77731b25af159ab4609reed@google.com const SkClipStack& clipStack, SkRegion* 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 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip.op(0, 0, 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) { 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com updateClip->op(x, y, x + width, y + height, 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::kDifference_Op); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1228a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fDevice->setMatrixClip(*fMatrix, fClip, 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) { 2178a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fCanvas = canvas; 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com canvas->updateDeviceCMCache(); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2207d7ca79c3e6e6be7b7849b0d9a7fe26effb89c38reed@google.com fClipStack = &canvas->getTotalClipStack(); 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = canvas->getBounder(); 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = canvas->fMCRec->fTopLayer; 2238a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fSkipEmptyClips = skipEmptyClips; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip over recs with empty clips 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fSkipEmptyClips) { 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = fCurrLayer->fNext; 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fCurrLayer) { 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* rec = fCurrLayer; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = rec->fMatrix; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = &rec->fClip; 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = rec->fDevice; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fDevice->accessBitmap(true); 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = rec->fPaint; 242f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fMVMatrix = rec->fMVMatrix; 243f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExtMatrix = rec->fExtMatrix; 244f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = rec->fNext; 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->setClip(fClip); 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fCurrLayer may be NULL now 251199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com 252d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack); 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2574b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* getDevice() const { return fDevice; } 2596f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getX() const { return fDevice->getOrigin().x(); } 2606f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getY() const { return fDevice->getOrigin().y(); } 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& getMatrix() const { return *fMatrix; } 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& getClip() const { return *fClip; } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* getPaint() const { return fPaint; } 2646f8f292aa768869a9e85c314b124875f57504f2creed@google.com 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* fCurrLayer; 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; // May be null. 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool8 fSkipEmptyClips; 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkDraw INHERITED; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper { 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) { 2794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fCanvas = canvas; 2804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper = paint.getLooper(); 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = canvas->getDrawFilter(); 2824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 2834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fSaveCount = canvas->getSaveCount(); 2844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = false; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com if (fLooper) { 2874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper->init(canvas); 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 2914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com ~AutoDrawLooper() { 2924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fCanvas->getSaveCount() == fSaveCount); 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 2954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com const SkPaint& paint() const { 2964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fPaint); 2974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return *fPaint; 2984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 2994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 3004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com bool next(SkDrawFilter::Type drawType); 3014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3032c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazyPaint; 3042c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkCanvas* fCanvas; 3052c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint& fOrigPaint; 3062c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawLooper* fLooper; 3072c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawFilter* fFilter; 3082c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 3092c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org int fSaveCount; 3102c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org bool fDone; 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.combool AutoDrawLooper::next(SkDrawFilter::Type drawType) { 314632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fPaint = NULL; 3154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com if (fDone) { 3164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return false; 3174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 318632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com 319632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fLooper || fFilter) { 320632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com SkPaint* paint = fLazyPaint.set(fOrigPaint); 321632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fLooper && !fLooper->next(fCanvas, paint)) { 322632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fDone = true; 323632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com return false; 324632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 325632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fFilter) { 326632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fFilter->filter(paint, drawType); 327632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (NULL == fLooper) { 328632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com // no looper means we only draw once 329632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fDone = true; 330632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 331632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 332632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fPaint = paint; 333632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } else { 3344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = true; 3354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = &fOrigPaint; 3364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 3374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 338632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com // call this after any possible paint modifiers 339632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fPaint->nothingToDraw()) { 3404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 3414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return false; 3424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 3434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return true; 3444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com} 3454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Stack helper for managing a SkBounder. In the destructor, if we were 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com given a bounder, we call its commit() method, signifying that we are 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com done accumulating bounds for that draw. 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit { 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBounderCommit() { 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fBounder) { 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->commit(); 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoValidator { 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AutoValidator(SkDevice* device) : fDevice(device) {} 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~AutoValidator() { 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& bm = fDevice->accessBitmap(false); 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bm.config() == SkBitmap::kARGB_4444_Config) { 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int y = 0; y < bm.height(); y++) { 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPMColor16* p = bm.getAddr16(0, y); 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = 0; x < bm.width(); x++) { 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16 c = p[x]; 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor16Assert(c); 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* fDevice; 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls ////////////////// 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_BEGIN(paint, type) \ 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ 3894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com AutoDrawLooper looper(this, paint); \ 3904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com while (looper.next(type)) { \ 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit ac(fBounder); \ 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter iter(this); 3934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END } 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////// 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::init(SkDevice* device) { 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = NULL; 4003c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fLocalBoundsCompareType.setEmpty(); 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 4023c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fLocalBoundsCompareTypeBW.setEmpty(); 403ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 404199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = NULL; 405447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org fDeviceCMDirty = false; 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.push_back(); 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (fMCRec) MCRec(NULL, 0); 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL)); 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = fMCRec->fLayer; 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fNext = NULL; 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4143c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fExternalMatrix.reset(); 4153c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fExternalInverse.reset(); 416f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 417f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setDevice(device); 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 421cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas() 422cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4238d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org inc_canvas(); 424cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com 4258d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(NULL); 4268d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org} 4278d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(SkDevice* device) 429ea4ac97dec2eb291139bd906939e0d2e05cdd7efmike@reedtribe.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->init(device); 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap) 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 439cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref(); 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() { 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // free up the contents of our deque 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restoreToCount(1); // restore everything but the last 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); // restore the last, since we're going away 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4478d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkSafeUnref(fBounder); 448b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_canvas(); 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) { 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fBounder, bounder); 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder; 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const { 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fFilter; 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return filter; 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::getDevice() const { 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 4704c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 4714c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com MCRec* rec = (MCRec*)iter.next(); 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec->fLayer->fDevice; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4769266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.comSkDevice* SkCanvas::getTopDevice() const { 4779266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com return fMCRec->fTopLayer->fDevice; 4789266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com} 4799266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::setDevice(SkDevice* device) { 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 4824c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 4834c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com MCRec* rec = (MCRec*)iter.next(); 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* rootDevice = rec->fLayer->fDevice; 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice == device) { 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Notify the devices that they are going in/out of scope, so they can do 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com things like lock/unlock their pixels, etc. 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device) { 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->lockPixels(); 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice) { 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice->unlockPixels(); 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice = device; 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 5054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Now we update our initial region to have the bounds of the new device, 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com and then intersect all of the clips in our stack with these bounds, 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com to ensure that we can't draw outside of the device's bounds (and trash 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memory). 5104b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTE: this is only a partial-fix, since if the new device is larger than 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the previous one, we don't know how to "enlarge" the clips in our stack, 5134b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com so drawing may be artificially restricted. Without keeping a history of 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reconstruct the correct clips, so this approximation will have to do. 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The caller really needs to restore() back to the base if they want to 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com accurately take advantage of the new device bounds. 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == device) { 5210017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com rec->fRasterClip->setEmpty(); 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5230017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com (void)rec->fRasterClip->setEmpty(); 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5255c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.reset(); 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute our total bounds for all devices 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 5294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now jam our 1st clip to be bounds, and intersect the rest with that 5330017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com rec->fRasterClip->setRect(bounds); 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((rec = (MCRec*)iter.next()) != NULL) { 5350017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 541af951c9bc4cbb6e60b430194fe5127ebe99c53fbreed@google.comSkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) { 542af951c9bc4cbb6e60b430194fe5127ebe99c53fbreed@google.com SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap))); 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 54751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 54851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 54951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 55051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 55151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 55251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return device->readPixels(srcRect, bitmap); 55351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 55451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 5554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com////////////////////////////////////////////////////////////////////////////// 5564b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 55751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.combool SkCanvas::readPixels(SkBitmap* bitmap) { 55851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 55951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 56051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 56151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 56251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkIRect bounds; 56351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com bounds.set(0, 0, device->width(), device->height()); 56451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return this->readPixels(bounds, bitmap); 56551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 56651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 56751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 56851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com SkDevice* device = this->getDevice(); 56951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (device) { 57051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com device->writePixels(bitmap, x, y); 57151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 57251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 57351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& totalClip = this->getTotalClip(); 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 5814b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 58346799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 584f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 585f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 586f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 587f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion clip; 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clip = totalClip; // make a copy 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 59246799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, clip, fClipStack, &clip); 593f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 594f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com layer->updateExternalMatrix(fExternalMatrix, 595f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalInverse); 596f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 603f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, 604d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com const SkRegion& clip, 605d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com const SkClipStack& clipStack) { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(device); 607199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com if (fLastDeviceToGainFocus != device) { 608d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com device->gainFocus(this, matrix, clip, clipStack); 609199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com fLastDeviceToGainFocus = device; 610199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com } 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 6174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 6204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 6234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.save(); 6255c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 6265c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDevice* device = canvas->getLayerDevice(i); 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this before we create the layer. We don't call the public save() since 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // that would invoke a possibly overridden virtual 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = this->internalSave(flags); 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 687bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect clipBounds; 688bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!this->getClipDeviceBounds(&clipBounds)) { 689f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com return count; 690f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 692bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ir; 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 6954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 700bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds_affects_clip(flags)) { 7010017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fMCRec->fRasterClip->setEmpty(); 702bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7095c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 7120017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) { 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 719e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com SkDevice* device = this->createLayerDevice(config, ir.width(), ir.height(), 720e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com isOpaque); 721e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com if (NULL == device) { 722e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com SkDebugf("Unable to create device for layer."); 723e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com return count; 724e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com } 725e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 7266f8f292aa768869a9e85c314b124875f57504f2creed@google.com device->setOrigin(ir.fLeft, ir.fTop); 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 760ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7625c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.restore(); 76388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com // reserve our layer (if any) 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 7796f8f292aa768869a9e85c314b124875f57504f2creed@google.com const SkIPoint& origin = layer->fDevice->getOrigin(); 7806f8f292aa768869a9e85c314b124875f57504f2creed@google.com this->drawDevice(layer->fDevice, origin.x(), origin.y(), 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fPaint); 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // reset this, since drawDevice will have set it to true 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 78688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 7875c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 7885c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fMCStack.count() > count) { 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) { 809a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com return bitmap.width() <= 0 || bitmap.height() <= 0 810a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#ifndef SK_ALLOW_OVER_32K_BITMAPS 811a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com || bitmap.width() > 32767 || bitmap.height() > 32767 812a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#endif 813a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com ; 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 816f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint lazy; 8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 8242c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org paint = lazy.init(); 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8262c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawDevice(SkDevice* device, int x, int y, 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 8374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), 8404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint()); 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 850ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 857ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 864ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 871ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 878ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 885ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 8934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 900c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 9015c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 9025c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 905ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 90898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // for these simpler matrices, we can stay a rect ever after applying 90998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 91098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 91198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 9150017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevRect(r, op, doAA); 9160017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(r, op, doAA); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 91898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // since we're rotate or some such thing, we convert the rect to a path 91998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 92098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 92198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 925c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com return this->SkCanvas::clipPath(path, op, doAA); 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9290017708a5bcb6d0fbff0fac565085bef65de7433reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 930c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com const SkPath& devPath, SkRegion::Op op, bool doAA) { 931759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // base is used to limit the size (and therefore memory allocation) of the 932759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // region that results from scan converting devPath. 933759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com SkRegion base; 934759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com 935819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kIntersect_Op == op) { 936759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // since we are intersect, we can do better (tighter) with currRgn's 937759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // bounds, than just using the device. However, if currRgn is complex, 938759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // our region blitter may hork, so we do that case in two steps. 9390017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (currClip->isRect()) { 9400017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->setPath(devPath, *currClip, doAA); 941759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } else { 9420017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com base.setRect(currClip->getBounds()); 9430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 9440017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 9450017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 946759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } 947819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 948819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkBitmap& bm = canvas->getDevice()->accessBitmap(false); 949819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com base.setRect(0, 0, bm.width(), bm.height()); 950819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 951819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kReplace_Op == op) { 9520017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->setPath(devPath, base, doAA); 953819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 9540017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 9550017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 9560017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 957819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 958819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 959819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 960819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 961c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 9625c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 9635c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 966ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9715c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // if we called path.swap() we could avoid a deep copy of this path 9720017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevPath(devPath, op, doAA); 9735c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9740017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 9785c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 9795c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 982ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeDirtyBW = true; 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // todo: signal fClipStack that we have a region, and therefore (I guess) 9855c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // we have to ignore it, and use the region directly? 9865c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(rgn.getBounds()); 9875c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 9880017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(rgn, op); 9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 991819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG 992819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const { 993819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // construct clipRgn from the clipstack 994819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkDevice* device = this->getDevice(); 995819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkIRect ir; 996819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com ir.set(0, 0, device->width(), device->height()); 9970017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip tmpClip(ir); 998819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 999819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkClipStack::B2FIter iter(fClipStack); 1000819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkClipStack::B2FIter::Clip* clip; 1001819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com while ((clip = iter.next()) != NULL) { 1002819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (clip->fPath) { 10030017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA); 1004819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else if (clip->fRect) { 1005819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com clip->fRect->round(&ir); 10060017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com tmpClip.op(ir, clip->fOp); 1007819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 10080017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com tmpClip.setEmpty(); 1009819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1010819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1011819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 10126f8f292aa768869a9e85c314b124875f57504f2creed@google.com#if 0 // enable this locally for testing 1013819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // now compare against the current rgn 1014819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkRegion& rgn = this->getTotalClip(); 10150017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkASSERT(rgn == tmpClip); 101602878b844c5cd3f17d48842da3ccf44a66621501reed@google.com#endif 1017819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1018819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif 1019819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 10205c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com/////////////////////////////////////////////////////////////////////////////// 10215c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 1022ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.comvoid SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 1024ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 1025ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com fLocalBoundsCompareTypeBW; 1026ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com 1027ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com if (!this->getClipBounds(&r, et)) { 1028ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.setEmpty(); 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1030ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com rCompare.set(SkScalarToCompareType(r.fLeft), 1031ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fTop), 1032ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fRight), 1033ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com SkScalarToCompareType(r.fBottom)); 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1037d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/* current impl ignores edgetype, and relies on 1038d252db03d9650013b545ef9781fe993c07f8f314reed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 1039d252db03d9650013b545ef9781fe993c07f8f314reed@android.com antialiasing (worst case) 1040d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */ 1041ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.combool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 1042116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 1043116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org if (!rect.hasValidCoordinates()) 1044116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org return true; 1045116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 10460017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) { 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10508d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (fMCRec->fMatrix->hasPerspective()) { 1051a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 1052a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 1053a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 1054a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 10550017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); 1056a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 1057ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 1058d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 1059a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 1060a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1061a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1062a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1063a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1064a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1065a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1066a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1067a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1068a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1069a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1070a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 1075d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return path.isEmpty() || this->quickReject(path.getBounds(), et); 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const { 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* current impl ignores edgetype, and relies on 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com getLocalClipBoundsCompareType(), which always returns a value assuming 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialiasing (worst case) 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10840017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) { 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1088aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userT = SkScalarToCompareType(top); 1089aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com SkScalarCompareType userB = SkScalarToCompareType(bottom); 10904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for invalid user Y coordinates (i.e. empty) 1092d252db03d9650013b545ef9781fe993c07f8f314reed@android.com // reed: why do we need to do this check, since it slows us down? 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (userT >= userB) { 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we are above or below the local clip bounds 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return userT >= clipR.fBottom || userB <= clipR.fTop; 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 1103bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ibounds; 1104bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!getClipDeviceBounds(&ibounds)) { 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1108d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 1109d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 1110d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 111172dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 111272dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 111372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1114d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1115d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1116d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 1118bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkRect r; 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // adjust it outwards if we are antialiasing 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inset = (kAA_EdgeType == et); 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ibounds.fRight + inset, ibounds.fBottom + inset); 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1128bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 11290017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com const SkRasterClip& clip = *fMCRec->fRasterClip; 1130bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (clip.isEmpty()) { 1131bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds) { 1132bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com bounds->setEmpty(); 1133bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1134bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return false; 1135bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1136bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 1137bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (NULL != bounds) { 1138bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com *bounds = clip.getBounds(); 1139bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1140bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return true; 1141bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1142bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1147bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const { 11480017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType; 11490017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isRect()) return kRect_ClipType; 1150bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return kComplex_ClipType; 1151bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1152bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 11540017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->forceGetBW(); 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11577d7ca79c3e6e6be7b7849b0d9a7fe26effb89c38reed@google.comconst SkClipStack& SkCanvas::getTotalClipStack() const { 11587d7ca79c3e6e6be7b7849b0d9a7fe26effb89c38reed@google.com return fClipStack; 11597d7ca79c3e6e6be7b7849b0d9a7fe26effb89c38reed@google.com} 11607d7ca79c3e6e6be7b7849b0d9a7fe26effb89c38reed@google.com 1161f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::setExternalMatrix(const SkMatrix* matrix) { 1162f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (NULL == matrix || matrix->isIdentity()) { 1163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fUseExternalMatrix) { 1164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; 1165f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1166f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = false; 1167f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 1168f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fUseExternalMatrix = true; 1169f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) 11704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1171f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fExternalMatrix = *matrix; 1172f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com matrix->invert(&fExternalInverse); 1173f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1174f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1176e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.comSkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, 1177e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com int width, int height, 1178e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com bool isOpaque) { 117988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com SkDevice* device = this->getTopDevice(); 1180cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com if (device) { 1181cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDeviceForSaveLayer(config, width, height, 1182cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com isOpaque); 1183e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1184cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return NULL; 1185e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1188e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.comSkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, 1189e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com int width, int height, 1190e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com bool isOpaque) { 1191e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com SkDevice* device = this->getDevice(); 1192e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com if (device) { 1193cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDevice(config, width, height, isOpaque); 1194e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1195e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com return NULL; 1196e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 1197e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com} 1198e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 1199e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12042a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) { 12052a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com SkDrawIter iter(this); 12062a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com 12072a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com while (iter.next()) { 12082a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com iter.fDevice->clear(color); 12092a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com } 12102a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com} 12112a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 1213fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1214fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com} 1215fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com 1216fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) { 12174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPaint(iter, looper.paint()); 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) 12354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 12524e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawRect(iter, r, looper.paint()); 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1262fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1263d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect storage; 1264d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 1265d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (this->quickReject(paint.computeFastBounds(bounds, &storage), 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1270fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isEmpty()) { 1271fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isInverseFillType()) { 1272fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1273fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 1274fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com return; 1275fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 12804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPath(iter, path, looper.paint()); 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint || (paint->getMaskFilter() == NULL)) { 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect fastBounds; 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fastBounds.set(x, y, 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x + SkIntToScalar(bitmap.width()), 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y + SkIntToScalar(bitmap.height())); 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(fastBounds, paint2EdgeType(paint))) { 12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 1302f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13059987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis 13069987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 13079987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13119987ec3791336bad6af5cbe513564786b2df55aareed@google.com 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this now, to avoid the cost of calling extract for RLE bitmaps 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(dst, paint2EdgeType(paint))) { 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13169987ec3791336bad6af5cbe513564786b2df55aareed@google.com 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmapPtr = &bitmap; 13189987ec3791336bad6af5cbe513564786b2df55aareed@google.com 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 1320878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkRect tmpSrc; 1321878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (src) { 1322878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(*src); 1323878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // if the extract process clipped off the top or left of the 1324878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com // original, we adjust for that here to get the position right. 1325878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fLeft > 0) { 1326878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fRight -= tmpSrc.fLeft; 1327878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fLeft = 0; 1328fead49e3c43e67cf9648ec1999b34da959e1e36breed@android.com } 1329878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com if (tmpSrc.fTop > 0) { 1330878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fBottom -= tmpSrc.fTop; 1331878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.fTop = 0; 1332878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } 1333878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com } else { 1334878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1335878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com SkIntToScalar(bitmap.height())); 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1337878999965b977c4ed771c3d655f9e23ef9b5adb1reed@android.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 13389987ec3791336bad6af5cbe513564786b2df55aareed@google.com 1339f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // ensure that src is "valid" before we pass it to our internal routines 1340f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // and to SkDevice. i.e. sure it is contained inside the original bitmap. 1341f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkIRect tmpISrc; 1342f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (src) { 1343f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); 13442ade0863c3af14d274561cc7cb6e628bb9862761reed@google.com if (!tmpISrc.intersect(*src)) { 13452ade0863c3af14d274561cc7cb6e628bb9862761reed@google.com return; 13462ade0863c3af14d274561cc7cb6e628bb9862761reed@google.com } 1347f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com src = &tmpISrc; 1348f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 1349f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13529987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 13539987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 13549987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 13559987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapRect(bitmap, src, dst, paint); 13569987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 13579987ec3791336bad6af5cbe513564786b2df55aareed@google.com 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 1361f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->internalDrawBitmap(bitmap, NULL, matrix, paint); 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1364f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 1365f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkMatrix& matrix, const SkPaint& paint) { 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 13679b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 13684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 13699b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 13714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13739b0390626f73cc88c05c90de64bfe0481e808f14reed@android.com 13744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13779987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 13789987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkIRect& center, const SkRect& dst, 13799987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkPaint* paint) { 13809987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t w = bitmap.width(); 13819987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t h = bitmap.height(); 13829987ec3791336bad6af5cbe513564786b2df55aareed@google.com 13839987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkIRect c = center; 13849987ec3791336bad6af5cbe513564786b2df55aareed@google.com // pin center to the bounds of the bitmap 13859987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fLeft = SkMax32(0, center.fLeft); 13869987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fTop = SkMax32(0, center.fTop); 13879987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fRight = SkPin32(center.fRight, c.fLeft, w); 13889987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fBottom = SkPin32(center.fBottom, c.fTop, h); 13899987ec3791336bad6af5cbe513564786b2df55aareed@google.com 13909987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t srcX[4] = { 0, c.fLeft, c.fRight, w }; 13919987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t srcY[4] = { 0, c.fTop, c.fBottom, h }; 13929987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstX[4] = { 13939987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 13949987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 13959987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 13969987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstY[4] = { 13979987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 13989987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 13999987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 14009987ec3791336bad6af5cbe513564786b2df55aareed@google.com 14019987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstX[1] > dstX[2]) { 14029987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 14039987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[2] = dstX[1]; 14049987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 14059987ec3791336bad6af5cbe513564786b2df55aareed@google.com 14069987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstY[1] > dstY[2]) { 14079987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 14089987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[2] = dstY[1]; 14099987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 14109987ec3791336bad6af5cbe513564786b2df55aareed@google.com 14119987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkIRect s; 14129987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkRect d; 14139987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int y = 0; y < 3; y++) { 14149987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fTop = srcY[y]; 14159987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fBottom = srcY[y+1]; 14169987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fTop = dstY[y]; 14179987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fBottom = dstY[y+1]; 14189987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int x = 0; x < 3; x++) { 14199987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fLeft = srcX[x]; 14209987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fRight = srcX[x+1]; 14219987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fLeft = dstX[x]; 14229987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fRight = dstX[x+1]; 14239987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapRect(bitmap, &s, d, paint); 14249987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 14259987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 14269987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 14279987ec3791336bad6af5cbe513564786b2df55aareed@google.com 14289987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 14299987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 14309987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 14319987ec3791336bad6af5cbe513564786b2df55aareed@google.com 14329987ec3791336bad6af5cbe513564786b2df55aareed@google.com // Need a device entry-point, so gpu can use a mesh 14339987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapNine(bitmap, center, dst, paint); 14349987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 14359987ec3791336bad6af5cbe513564786b2df55aareed@google.com 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 14394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14434b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14494e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 14504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), 14534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint()); 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1458f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint { 1459f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic: 1460f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { 1461f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com SkDevice::TextFlags flags; 1462f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com if (device->filterTextFlags(paint, &flags)) { 1463a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com SkPaint* newPaint = fLazy.set(paint); 1464f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setFlags(flags.fFlags); 1465f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setHinting(flags.fHinting); 1466f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = newPaint; 1467f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } else { 1468f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = &paint; 1469f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1470f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1471f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1472f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com const SkPaint& paint() const { return *fPaint; } 1473f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1474f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate: 14752c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 14762c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazy; 1477f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com}; 1478f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 147952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 148052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const SkRect& r, SkScalar textSize) { 148117b78946096265d80215a6c946286ecaa35ea7edepoger@google.com if (paint.getStyle() == SkPaint::kFill_Style) { 148252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, paint); 148352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else { 148452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint p(paint); 148517b78946096265d80215a6c946286ecaa35ea7edepoger@google.com p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 148652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, p); 148752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 148852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 148952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 149052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 149152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const char text[], size_t byteLength, 149252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar x, SkScalar y) { 149352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkASSERT(byteLength == 0 || text != NULL); 149452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 149552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com // nothing to draw 149652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (text == NULL || byteLength == 0 || 149752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fClip->isEmpty() || 149852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 149952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 150052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 150152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 150252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar width = 0; 150352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPoint start; 150452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 150552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(0, 0); // to avoid warning 150652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 150752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 150852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com width = paint.measureText(text, byteLength); 150952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 151052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offsetX = 0; 151152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 151252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = SkScalarHalf(width); 151352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 151452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = width; 151552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 151652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(x - offsetX, y); 151752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 151852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 151952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (0 == width) { 152052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 152152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 152252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 152352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com uint32_t flags = paint.getFlags(); 152452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 152552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & (SkPaint::kUnderlineText_Flag | 152652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 152752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar textSize = paint.getTextSize(); 152852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 152952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkRect r; 153052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 153152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fLeft = start.fX; 153252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fRight = start.fX + width; 153352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 153452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kUnderlineText_Flag) { 153552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 153652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 153752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 153852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 153952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 154052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 154152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kStrikeThruText_Flag) { 154252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 154352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 154452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 154552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 154652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 154752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 154852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 154952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 155052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 15534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 15548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 15564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1557f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 155852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawTextDecorations(iter, dfp.paint(), 155952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com static_cast<const char*>(text), byteLength, x, y); 15608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 15668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 15674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 15684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 15704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 15718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 1572f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 15754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 15814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 15824b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 15844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 1586f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 15894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 15938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 15954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 15994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com matrix, looper.paint()); 16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1605cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com#ifdef ANDROID 1606cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.comvoid SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, 1607cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkPoint pos[], const SkPaint& paint, 1608cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkPath& path, const SkMatrix* matrix) { 16094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1610cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 1611cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com while (iter.next()) { 1612cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, 16134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint(), path, matrix); 1614cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com } 1615cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 16164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 1617cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com} 1618cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com#endif 1619cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 16248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 16254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 16264b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 16294e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com colors, xmode, indices, indexCount, 16304e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint()); 16318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16334e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1636cb60844b34766aad4151df5e87c144d4a57e9abereed@android.comvoid SkCanvas::drawData(const void* data, size_t length) { 1637cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com // do nothing. Subclasses may do something with the data 1638cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com} 1639cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com 16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 16438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1646845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 16478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 16488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 1650845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 16510baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 16528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 16548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1656845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 1660845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 16610baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 16684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 16748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 16758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 16764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 16854b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 17028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 17038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 17084b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 17118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(r); 17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 17278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(r, &storage), 17288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 17298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 17368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 17378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->quickReject(paint.computeFastBounds(oval, &storage), 17458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint2EdgeType(&paint))) { 17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 17518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addOval(oval); 17528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 17568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 17578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 17588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 17598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 17688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 17768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 17774b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1782f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 1783f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 17848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = save(); 17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com restoreToCount(saveCount); 17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 17928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 1794d642329293cce602ac24df8f585c14a98795da87reed@google.com SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDevice* SkCanvas::LayerIter::device() const { 18118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 18158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 18168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 1829