SkCanvas.cpp revision 1f2f338e23789f3eef168dcbd8171a28820ba6c1
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" 111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h" 139c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h" 1774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h" 1845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h" 200017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h" 214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalarCompare.h" 2397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 2552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h" 26a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h" 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2982ce2b8afb7c13c2a9f1b549a2a80dfca06bbf61reed@google.comSK_DEFINE_INST_COUNT(SkBounder) 3015e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.comSK_DEFINE_INST_COUNT(SkCanvas) 3182ce2b8afb7c13c2a9f1b549a2a80dfca06bbf61reed@google.comSK_DEFINE_INST_COUNT(SkDrawFilter) 3282ce2b8afb7c13c2a9f1b549a2a80dfca06bbf61reed@google.com 33da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing... 34da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT 3515e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gLayerCounter; 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gRecCounter; 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gCanvasCounter; 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_layer() 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_layer() 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_rec() 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_rec() 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_canvas() 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_canvas() 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 59ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#ifdef SK_DEBUG 60ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#include "SkPixelRef.h" 61ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 62f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com/* 63f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * Some pixelref subclasses can support being "locked" from another thread 64f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * during the lock-scope of skia calling them. In these instances, this balance 65f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * check will fail, but may not be indicative of a problem, so we allow a build 66f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * flag to disable this check. 67f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * 68f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * Potentially another fix would be to have a (debug-only) virtual or flag on 69f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * pixelref, which could tell us at runtime if this check is valid. That would 70f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * eliminate the need for this heavy-handed build check. 71f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com */ 72f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK 73f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.comclass AutoCheckLockCountBalance { 74f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.compublic: 75f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ } 76f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com}; 77f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#else 78ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckLockCountBalance { 79ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic: 80ea033606a06d05d2d42aa7118409fee798e53167reed@google.com AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) { 81ea033606a06d05d2d42aa7118409fee798e53167reed@google.com fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0; 82ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 83ea033606a06d05d2d42aa7118409fee798e53167reed@google.com ~AutoCheckLockCountBalance() { 84ea033606a06d05d2d42aa7118409fee798e53167reed@google.com const int count = fPixelRef ? fPixelRef->getLockCount() : 0; 85ea033606a06d05d2d42aa7118409fee798e53167reed@google.com SkASSERT(count == fLockCount); 86ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 87ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 88ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate: 89ea033606a06d05d2d42aa7118409fee798e53167reed@google.com const SkPixelRef* fPixelRef; 90ea033606a06d05d2d42aa7118409fee798e53167reed@google.com int fLockCount; 91ea033606a06d05d2d42aa7118409fee798e53167reed@google.com}; 92f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#endif 93ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 94ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckNoSetContext { 95ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic: 96ea033606a06d05d2d42aa7118409fee798e53167reed@google.com AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) { 97ea033606a06d05d2d42aa7118409fee798e53167reed@google.com this->assertNoSetContext(fPaint); 98ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 99ea033606a06d05d2d42aa7118409fee798e53167reed@google.com ~AutoCheckNoSetContext() { 100ea033606a06d05d2d42aa7118409fee798e53167reed@google.com this->assertNoSetContext(fPaint); 101ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 102ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 103ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate: 104ea033606a06d05d2d42aa7118409fee798e53167reed@google.com const SkPaint& fPaint; 105ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 106ea033606a06d05d2d42aa7118409fee798e53167reed@google.com void assertNoSetContext(const SkPaint& paint) { 107ea033606a06d05d2d42aa7118409fee798e53167reed@google.com SkShader* s = paint.getShader(); 108ea033606a06d05d2d42aa7118409fee798e53167reed@google.com if (s) { 109ea033606a06d05d2d42aa7118409fee798e53167reed@google.com SkASSERT(!s->setContextHasBeenCalled()); 110ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 111ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 112ea033606a06d05d2d42aa7118409fee798e53167reed@google.com}; 113ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 114ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap) 115ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint) 116ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 117ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#else 118ea033606a06d05d2d42aa7118409fee798e53167reed@google.com #define CHECK_LOCKCOUNT_BALANCE(bitmap) 119ea033606a06d05d2d42aa7118409fee798e53167reed@google.com #define CHECK_SHADER_NOSETCONTEXT(paint) 120ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#endif 121ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 1222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint; 1232c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org 12497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() { 12597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com if (fSurfaceBase) { 126c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); 12797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com } 12897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com} 12997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1321f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/* This is the record we keep for each SkBaseDevice that the user installs. 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The clip/matrix/proc are fields that reflect the top of the save/restore 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stack. Whenever the canvas changes, it marks a dirty flag, and then before 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com these are used (assuming we're not on a layer) we rebuild these cache 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com values: they reflect the top of the save stack, but translated and clipped 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com by the device's XY offset and bitmap-bounds. 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM { 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fNext; 1411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* fDevice; 142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip fClip; 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* fMatrix; 1446f8f292aa768869a9e85c314b124875f57504f2creed@google.com SkPaint* fPaint; // may be null (in the future) 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1461f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas) 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fNext(NULL) { 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != device) { 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->ref(); 15040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com device->onAttachToCanvas(canvas); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com fDevice = device; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 15488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com ~DeviceCM() { 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fDevice) { 15840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com fDevice->onDetachFromCanvas(); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unref(); 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com SkDELETE(fPaint); 16288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 1634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 165045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkClipStack& clipStack, SkRasterClip* updateClip) { 1666f8f292aa768869a9e85c314b124875f57504f2creed@google.com int x = fDevice->getOrigin().x(); 1676f8f292aa768869a9e85c314b124875f57504f2creed@google.com int y = fDevice->getOrigin().y(); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = fDevice->width(); 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = fDevice->height(); 1704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x | y) == 0) { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &totalMatrix; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = totalClip; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = totalMatrix; 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.postTranslate(SkIntToScalar(-x), 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(-y)); 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1794b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com totalClip.translate(-x, -y, &fClip); 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // intersect clip, but don't translate it (yet) 1864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (updateClip) { 188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::kDifference_Op); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1923fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 1933fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fClip.isEmpty()) { 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect deviceR; 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com deviceR.set(0, 0, width, height); 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(deviceR.contains(fClip.getBounds())); 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 201f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 202f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2040e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com SkMatrix fMatrixStorage; 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each save/restore level in the stack. 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Since a level optionally copies the matrix and/or stack, we have pointers 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for these fields. If the value is copied for this level, the copy is 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stored in the ...Storage field, and the pointer points to that. If the 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value is not copied for this level, we ignore ...Storage, and just point 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com at the corresponding value in the previous level in the stack. 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec { 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* fNext; 2176c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org int fFlags; 2180017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 2190017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec 2200017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkDrawFilter* fFilter; // the current filter (or null) 2214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fLayer; 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* If there are any layers in the stack, this points to the top-most 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com one that is at or below this level in the stack (so we know what 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap/device to draw into from this level. This value is NOT 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reference counted, since the real owner is either our fLayer field, 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com or a previous one in a lower level.) 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 22988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com DeviceCM* fTopLayer; 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2316c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org MCRec(const MCRec* prev, int flags) : fFlags(flags) { 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != prev) { 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kMatrix_SaveFlag) { 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = *prev->fMatrix; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = prev->fMatrix; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kClip_SaveFlag) { 2410017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClipStorage = *prev->fRasterClip; 2420017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = &fRasterClipStorage; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2440017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = prev->fRasterClip; 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = prev->fFilter; 24882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeRef(fFilter); 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = prev->fTopLayer; 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no prev 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.reset(); 2534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 2550017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = &fRasterClipStorage; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = NULL; 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = NULL; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayer = NULL; 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't bother initializing fNext 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_rec(); 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~MCRec() { 26582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fFilter); 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fLayer); 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_rec(); 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2710017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkMatrix fMatrixStorage; 2720017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip fRasterClipStorage; 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw { 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2778a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 2784370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com canvas = canvas->canvasForDrawIter(); 2798a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fCanvas = canvas; 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com canvas->updateDeviceCMCache(); 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com fClipStack = &canvas->fClipStack; 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = canvas->getBounder(); 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = canvas->fMCRec->fTopLayer; 2858a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fSkipEmptyClips = skipEmptyClips; 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip over recs with empty clips 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fSkipEmptyClips) { 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = fCurrLayer->fNext; 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 296f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com const DeviceCM* rec = fCurrLayer; 297f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com if (rec && rec->fDevice) { 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = rec->fMatrix; 300045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 301045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = &rec->fClip; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = rec->fDevice; 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fDevice->accessBitmap(true); 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = rec->fPaint; 305f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = rec->fNext; 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->setClip(fClip); 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fCurrLayer may be NULL now 312199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3181f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* getDevice() const { return fDevice; } 3196f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getX() const { return fDevice->getOrigin().x(); } 3206f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getY() const { return fDevice->getOrigin().y(); } 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& getMatrix() const { return *fMatrix; } 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& getClip() const { return *fClip; } 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* getPaint() const { return fPaint; } 3246f8f292aa768869a9e85c314b124875f57504f2creed@google.com 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* fCurrLayer; 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; // May be null. 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool8 fSkipEmptyClips; 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkDraw INHERITED; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper { 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3388926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, 3398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com bool skipLayerForImageFilter = false) : fOrigPaint(paint) { 3404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fCanvas = canvas; 3414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper = paint.getLooper(); 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = canvas->getDrawFilter(); 3434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 3444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fSaveCount = canvas->getSaveCount(); 3458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fDoClearImageFilter = false; 3464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = false; 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 3498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkPaint tmp; 3508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com tmp.setImageFilter(fOrigPaint.getImageFilter()); 3518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // it would be nice if we had a guess at the bounds, instead of null 3528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com (void)canvas->internalSaveLayer(NULL, &tmp, 3538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkCanvas::kARGB_ClipLayer_SaveFlag, true); 3548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // we'll clear the imageFilter for the actual draws in next(), so 3558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // it will only be applied during the restore(). 3568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fDoClearImageFilter = true; 3578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3588926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 3594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com if (fLooper) { 3604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper->init(canvas); 361129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fIsSimple = false; 362129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } else { 363129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com // can we be marked as simple? 364129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fIsSimple = !fFilter && !fDoClearImageFilter; 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 36774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com ~AutoDrawLooper() { 3698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (fDoClearImageFilter) { 3708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fCanvas->internalRestore(); 3718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fCanvas->getSaveCount() == fSaveCount); 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 37474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com const SkPaint& paint() const { 3764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fPaint); 3774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return *fPaint; 3784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 37974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 380129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com bool next(SkDrawFilter::Type drawType) { 381129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fDone) { 382129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return false; 383129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } else if (fIsSimple) { 384129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fDone = true; 385129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fPaint = &fOrigPaint; 386129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return !fPaint->nothingToDraw(); 387129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } else { 388129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return this->doNext(drawType); 389129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 390fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 39174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3932c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazyPaint; 3942c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkCanvas* fCanvas; 3952c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint& fOrigPaint; 3962c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawLooper* fLooper; 3972c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawFilter* fFilter; 3982c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 3992c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org int fSaveCount; 4008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com bool fDoClearImageFilter; 4012c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org bool fDone; 402129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com bool fIsSimple; 403129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com 404129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com bool doNext(SkDrawFilter::Type drawType); 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 407129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 408632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fPaint = NULL; 409129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com SkASSERT(!fIsSimple); 410129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com SkASSERT(fLooper || fFilter || fDoClearImageFilter); 411632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com 412129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com SkPaint* paint = fLazyPaint.set(fOrigPaint); 4138926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 414129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fDoClearImageFilter) { 415129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com paint->setImageFilter(NULL); 416129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 4178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 418129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fLooper && !fLooper->next(fCanvas, paint)) { 419129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fDone = true; 420129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return false; 421129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 422129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fFilter) { 423971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com if (!fFilter->filter(paint, drawType)) { 424971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com fDone = true; 425971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com return false; 426971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com } 427129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (NULL == fLooper) { 428129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com // no looper means we only draw once 429632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fDone = true; 430632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 431129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 432129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fPaint = paint; 4338926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 434129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com // if we only came in here for the imagefilter, mark us as done 435129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (!fLooper && !fFilter) { 4364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = true; 4374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 4384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 439632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com // call this after any possible paint modifiers 440632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fPaint->nothingToDraw()) { 4414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 4424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return false; 4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 4444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return true; 4454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com} 4464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Stack helper for managing a SkBounder. In the destructor, if we were 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com given a bounder, we call its commit() method, signifying that we are 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com done accumulating bounds for that draw. 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit { 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBounderCommit() { 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fBounder) { 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->commit(); 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls ////////////////// 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ 46897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com this->predrawNotify(); \ 4698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com AutoDrawLooper looper(this, paint, true); \ 4708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com while (looper.next(type)) { \ 4718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkAutoBounderCommit ac(fBounder); \ 4728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkDrawIter iter(this); 4738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 4744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_BEGIN(paint, type) \ 47597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com this->predrawNotify(); \ 4764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com AutoDrawLooper looper(this, paint); \ 4774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com while (looper.next(type)) { \ 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit ac(fBounder); \ 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawIter iter(this); 4804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 4814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END } 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////// 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::init(SkBaseDevice* device) { 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = NULL; 4873c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org fLocalBoundsCompareType.setEmpty(); 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 4898f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com fAllowSoftClip = true; 49045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com fAllowSimplifyClip = false; 491447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org fDeviceCMDirty = false; 492b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount = 0; 49374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org fMetaData = NULL; 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.push_back(); 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (fMCRec) MCRec(NULL, 0); 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 49840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL)); 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = fMCRec->fLayer; 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fNext = NULL; 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 50297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com fSurfaceBase = NULL; 503f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setDevice(device); 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 507cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas() 508cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 5098d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org inc_canvas(); 51074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 5118d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(NULL); 5128d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org} 5138d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 5141f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkCanvas::SkCanvas(SkBaseDevice* device) 515ea4ac97dec2eb291139bd906939e0d2e05cdd7efmike@reedtribe.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->init(device); 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap) 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5251f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() { 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // free up the contents of our deque 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restoreToCount(1); // restore everything but the last 531b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org SkASSERT(0 == fSaveLayerCount); 5327c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); // restore the last, since we're going away 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5358d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkSafeUnref(fBounder); 53674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org SkDELETE(fMetaData); 537b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_canvas(); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) { 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fBounder, bounder); 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder; 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const { 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fFilter; 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return filter; 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 55574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() { 55674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org // metadata users are rare, so we lazily allocate it. If that changes we 55774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org // can decide to just make it a field in the device (rather than a ptr) 55874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org if (NULL == fMetaData) { 55974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org fMetaData = new SkMetaData; 56074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org } 56174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org return *fMetaData; 56274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org} 56374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 566bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() { 5671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 568bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org if (device) { 569bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org device->flush(); 570bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org } 571bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org} 572bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org 573210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.comSkISize SkCanvas::getDeviceSize() const { 5741f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* d = this->getDevice(); 575210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 576210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com} 577210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com 5781f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const { 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 580c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com MCRec* rec = (MCRec*) fMCStack.front(); 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec->fLayer->fDevice; 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 5860b53d59a24f667350b4282f88470713902409030reed@google.com if (updateMatrixClip) { 5870b53d59a24f667350b4282f88470713902409030reed@google.com const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 5880b53d59a24f667350b4282f88470713902409030reed@google.com } 5899266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com return fMCRec->fTopLayer->fDevice; 5909266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com} 5919266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com 5921f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::setDevice(SkBaseDevice* device) { 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 5944c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 5954c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com MCRec* rec = (MCRec*)iter.next(); 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 5971f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* rootDevice = rec->fLayer->fDevice; 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice == device) { 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6024b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device) { 60440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com device->onAttachToCanvas(this); 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice) { 60740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com rootDevice->onDetachFromCanvas(); 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice = device; 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 6144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Now we update our initial region to have the bounds of the new device, 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com and then intersect all of the clips in our stack with these bounds, 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com to ensure that we can't draw outside of the device's bounds (and trash 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memory). 6194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTE: this is only a partial-fix, since if the new device is larger than 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the previous one, we don't know how to "enlarge" the clips in our stack, 6224b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com so drawing may be artificially restricted. Without keeping a history of 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reconstruct the correct clips, so this approximation will have to do. 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The caller really needs to restore() back to the base if they want to 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com accurately take advantage of the new device bounds. 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 62942aea289cbf801997b653a906a37a7f7e948b645reed@google.com SkIRect bounds; 63042aea289cbf801997b653a906a37a7f7e948b645reed@google.com if (device) { 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 63242aea289cbf801997b653a906a37a7f7e948b645reed@google.com } else { 63342aea289cbf801997b653a906a37a7f7e948b645reed@google.com bounds.setEmpty(); 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 63542aea289cbf801997b653a906a37a7f7e948b645reed@google.com // now jam our 1st clip to be bounds, and intersect the rest with that 63642aea289cbf801997b653a906a37a7f7e948b645reed@google.com rec->fRasterClip->setRect(bounds); 63742aea289cbf801997b653a906a37a7f7e948b645reed@google.com while ((rec = (MCRec*)iter.next()) != NULL) { 63842aea289cbf801997b653a906a37a7f7e948b645reed@google.com (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); 63942aea289cbf801997b653a906a37a7f7e948b645reed@google.com } 64042aea289cbf801997b653a906a37a7f7e948b645reed@google.com 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6446850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.combool SkCanvas::readPixels(SkBitmap* bitmap, 6456850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com int x, int y, 6466850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com Config8888 config8888) { 6471f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 64851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 64951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 65051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 6516850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return device->readPixels(bitmap, x, y, config8888); 65251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 65351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 654c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 6551f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 656ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com if (!device) { 657ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com return false; 658ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com } 65974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 660daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com SkIRect bounds; 661c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bounds.set(0, 0, device->width(), device->height()); 662daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com if (!bounds.intersect(srcRect)) { 663daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com return false; 664c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 665c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 666c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkBitmap tmp; 667c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), 668c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bounds.height()); 669c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) { 670c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bitmap->swap(tmp); 671c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return true; 672c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } else { 67351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 67451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 67551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 67651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 677d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y, 678d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com Config8888 config8888) { 6791f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 68051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (device) { 681405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()), 682405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) { 683405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com device->accessBitmap(true); 684405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com device->writePixels(bitmap, x, y, config8888); 685405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com } 68651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 68751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 68851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 6894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() { 6904370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com return this; 6914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com} 6924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 698045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& totalClip = *fMCRec->fRasterClip; 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 7004b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 70246799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 704045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip(totalClip); 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 70646799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, clip, fClipStack, &clip); 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 7174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 7204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 7234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7246c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org if (SkCanvas::kClip_SaveFlag & flags) { 7256c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org fClipStack.save(); 7266c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org } 7275c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 7511f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = canvas->getLayerDevice(i); 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 780a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 781a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SkIRect* intersection) { 782bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect clipBounds; 783bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!this->getClipDeviceBounds(&clipBounds)) { 784a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 785f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 786bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ir; 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 7894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 794bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds_affects_clip(flags)) { 7950017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fMCRec->fRasterClip->setEmpty(); 796bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 797a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8035c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); 804a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 8070017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) { 808a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 809a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org } 810a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 811a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org if (intersection) { 812a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org *intersection = ir; 813a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org } 814a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return true; 815a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org} 816a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 817a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 818a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SaveFlags flags) { 8198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return this->internalSaveLayer(bounds, paint, flags, false); 8208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com} 8218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 8228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, 8238926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SaveFlags flags, bool justForImageFilter) { 824a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org // do this before we create the layer. We don't call the public save() since 825a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org // that would invoke a possibly overridden virtual 826a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org int count = this->internalSave(flags); 827a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 828a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org fDeviceCMDirty = true; 829a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 830a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SkIRect ir; 831a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org if (!this->clipRectBounds(bounds, flags, &ir)) { 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 835b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com // Kill the imagefilter if our device doesn't allow it 836b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkLazyPaint lazyP; 837b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com if (paint && paint->getImageFilter()) { 838b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 8398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (justForImageFilter) { 8408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // early exit if the layer was just for the imageFilter 8418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return count; 8428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 843b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkPaint* p = lazyP.set(*paint); 844b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com p->setImageFilter(NULL); 845b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com paint = p; 846b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com } 847b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com } 848b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8521f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device; 85376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com if (paint && paint->getImageFilter()) { 85476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com device = this->createCompatibleDevice(config, ir.width(), ir.height(), 85576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com isOpaque); 85676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } else { 85776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com device = this->createLayerDevice(config, ir.width(), ir.height(), 85876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com isOpaque); 85976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 860e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com if (NULL == device) { 861e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com SkDebugf("Unable to create device for layer."); 862e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com return count; 863e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com } 864e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 8656f8f292aa768869a9e85c314b124875f57504f2creed@google.com device->setOrigin(ir.fLeft, ir.fTop); 86640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this)); 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 873b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount += 1; 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9016c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) { 9026c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org fClipStack.restore(); 9036c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org } 9046c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org 90588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com // reserve our layer (if any) 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 9216f8f292aa768869a9e85c314b124875f57504f2creed@google.com const SkIPoint& origin = layer->fDevice->getOrigin(); 9228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 9238926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com layer->fPaint); 9248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // reset this, since internalDrawDevice will have set it to true 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9267c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 927b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org SkASSERT(fSaveLayerCount > 0); 928b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount -= 1; 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 93188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 94374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 944b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com int n = this->getSaveCount() - count; 945b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com for (int i = 0; i < n; ++i) { 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9507c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const { 951b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org return fSaveLayerCount > 0; 9527c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com} 9537c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// can't draw it if its empty, or its too big for a fixed-point width or height 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool reject_bitmap(const SkBitmap& bitmap) { 9582853429d39b16c1bd09d1e88147a608908f284dfreed@google.com return bitmap.width() <= 0 || bitmap.height() <= 0; 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9619bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reject_bitmap(bitmap)) { 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9672c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint lazy; 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 9692c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org paint = lazy.init(); 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9719bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 9729bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com SkDEBUGCODE(bitmap.validate();) 9739bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com CHECK_LOCKCOUNT_BALANCE(bitmap); 9749bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 9759bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 9769bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 9779bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com while (iter.next()) { 9789bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 9799bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com } 9809bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 9819bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com LOOPER_END 9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9841f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 9858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com const SkPaint* paint) { 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 9928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 9941f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* dstDev = iter.fDevice; 99576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com paint = &looper.paint(); 99676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkImageFilter* filter = paint->getImageFilter(); 99776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 9988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (filter && !dstDev->canHandleImageFilter(filter)) { 9999c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org SkDeviceImageFilterProxy proxy(dstDev); 100076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkBitmap dst; 1001b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com const SkBitmap& src = srcDev->accessBitmap(false); 1002fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org SkMatrix matrix = *iter.fMatrix; 1003fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 1004fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org if (filter->filterImage(&proxy, src, matrix, &dst, &pos)) { 10055efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com SkPaint tmpUnfiltered(*paint); 10065efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered.setImageFilter(NULL); 10075efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered); 100876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 100976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } else { 1010b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 101176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 10178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com const SkPaint* paint) { 10188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkDEBUGCODE(bitmap.validate();) 1019ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_LOCKCOUNT_BALANCE(bitmap); 1020fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (reject_bitmap(bitmap)) { 10228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return; 10238926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 1024fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkPaint tmp; 10268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (NULL == paint) { 10278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint = &tmp; 10288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 1029fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1031fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com while (iter.next()) { 10338926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint = &looper.paint(); 10348926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkImageFilter* filter = paint->getImageFilter(); 10358926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 10368926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 10379c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org SkDeviceImageFilterProxy proxy(iter.fDevice); 10388926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkBitmap dst; 1039fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org SkMatrix matrix = *iter.fMatrix; 1040fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 1041fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org if (filter->filterImage(&proxy, bitmap, matrix, &dst, &pos)) { 10425efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com SkPaint tmpUnfiltered(*paint); 10435efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered.setImageFilter(NULL); 10445efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(), 10455efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered); 10468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } else { 10488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 10498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 10518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_END 10528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com} 10538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 10964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1103c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1104da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT 1105da17f758442f16747af39f8fbaed9c097048519creed@google.com if (SkRegion::kIntersect_Op == op) { 1106da17f758442f16747af39f8fbaed9c097048519creed@google.com if (fMCRec->fRasterClip->isEmpty()) { 1107da17f758442f16747af39f8fbaed9c097048519creed@google.com return false; 1108da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1109da17f758442f16747af39f8fbaed9c097048519creed@google.com 11103b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(rect)) { 1111da17f758442f16747af39f8fbaed9c097048519creed@google.com fDeviceCMDirty = true; 1112da17f758442f16747af39f8fbaed9c097048519creed@google.com fLocalBoundsCompareTypeDirty = true; 1113da17f758442f16747af39f8fbaed9c097048519creed@google.com 1114da17f758442f16747af39f8fbaed9c097048519creed@google.com fClipStack.clipEmpty(); 1115da17f758442f16747af39f8fbaed9c097048519creed@google.com return fMCRec->fRasterClip->setEmpty(); 1116da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1117da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1118da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif 1119da17f758442f16747af39f8fbaed9c097048519creed@google.com 11205c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 11215c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 11248f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com doAA &= fAllowSoftClip; 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 112798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // for these simpler matrices, we can stay a rect ever after applying 112898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 112998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 113098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 11340017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevRect(r, op, doAA); 11350017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(r, op, doAA); 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 113798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // since we're rotate or some such thing, we convert the rect to a path 113898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 113998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 114098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 1144c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com return this->SkCanvas::clipPath(path, op, doAA); 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11480017708a5bcb6d0fbff0fac565085bef65de7433reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 1149c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com const SkPath& devPath, SkRegion::Op op, bool doAA) { 1150759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // base is used to limit the size (and therefore memory allocation) of the 1151759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // region that results from scan converting devPath. 1152759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com SkRegion base; 1153759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com 1154819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kIntersect_Op == op) { 1155759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // since we are intersect, we can do better (tighter) with currRgn's 1156759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // bounds, than just using the device. However, if currRgn is complex, 1157759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // our region blitter may hork, so we do that case in two steps. 11580017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (currClip->isRect()) { 1159b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org // FIXME: we should also be able to do this when currClip->isBW(), 1160b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org // but relaxing the test above triggers GM asserts in 1161b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org // SkRgnBuilder::blitH(). We need to investigate what's going on. 1162b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org return currClip->setPath(devPath, currClip->bwRgn(), doAA); 1163759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } else { 11640017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com base.setRect(currClip->getBounds()); 11650017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 11660017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 11670017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 1168759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } 1169819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 11701f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com const SkBaseDevice* device = canvas->getDevice(); 1171ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com if (!device) { 1172ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com return currClip->setEmpty(); 1173ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com } 1174ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com 1175a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org base.setRect(0, 0, device->width(), device->height()); 1176819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1177819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kReplace_Op == op) { 11780017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->setPath(devPath, base, doAA); 1179819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 11800017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 11810017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 11820017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 1183819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1184819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1185819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1186819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 11874ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.combool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 11884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (rrect.isRect()) { 11894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 11904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA); 11914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } else { 11924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkPath path; 11934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com path.addRRect(rrect); 11944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 11954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return this->SkCanvas::clipPath(path, op, doAA); 11964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 11974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 11984ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 1199c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1200da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT 1201da17f758442f16747af39f8fbaed9c097048519creed@google.com if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1202da17f758442f16747af39f8fbaed9c097048519creed@google.com if (fMCRec->fRasterClip->isEmpty()) { 1203da17f758442f16747af39f8fbaed9c097048519creed@google.com return false; 1204da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1205fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12063b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(path.getBounds())) { 1207da17f758442f16747af39f8fbaed9c097048519creed@google.com fDeviceCMDirty = true; 1208da17f758442f16747af39f8fbaed9c097048519creed@google.com fLocalBoundsCompareTypeDirty = true; 1209fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1210da17f758442f16747af39f8fbaed9c097048519creed@google.com fClipStack.clipEmpty(); 1211da17f758442f16747af39f8fbaed9c097048519creed@google.com return fMCRec->fRasterClip->setEmpty(); 1212da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1213da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1214da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif 1215da17f758442f16747af39f8fbaed9c097048519creed@google.com 12165c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 12175c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 12208f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com doAA &= fAllowSoftClip; 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1225fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // Check if the transfomation, or the original path itself 1226fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // made us empty. Note this can also happen if we contained NaN 1227fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // values. computing the bounds detects this, and will set our 1228fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1229fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com if (devPath.getBounds().isEmpty()) { 1230fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // resetting the path will remove any NaN or other wanky values 1231fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // that might upset our scan converter. 1232fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com devPath.reset(); 1233fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com } 1234fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com 12355c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // if we called path.swap() we could avoid a deep copy of this path 12360017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevPath(devPath, op, doAA); 12375c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 123845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (fAllowSimplifyClip) { 123945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com devPath.reset(); 124045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com devPath.setFillType(SkPath::kInverseEvenOdd_FillType); 124145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com const SkClipStack* clipStack = getClipStack(); 124245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); 124345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com const SkClipStack::Element* element; 124445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com while ((element = iter.next())) { 124545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkClipStack::Element::Type type = element->getType(); 124645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (type == SkClipStack::Element::kEmpty_Type) { 124745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com continue; 124845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 124945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkPath operand; 125045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (type == SkClipStack::Element::kRect_Type) { 125145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com operand.addRect(element->getRect()); 125245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } else if (type == SkClipStack::Element::kPath_Type) { 125345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com operand = element->getPath(); 125445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } else { 125545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkDEBUGFAIL("Unexpected type."); 125645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 125745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkRegion::Op elementOp = element->getOp(); 125845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (elementOp == SkRegion::kReplace_Op) { 125945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com devPath = operand; 126045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } else { 126145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com Op(devPath, operand, (SkPathOp) elementOp, &devPath); 126245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 126396fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com // if the prev and curr clips disagree about aa -vs- not, favor the aa request. 126496fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com // perhaps we need an API change to avoid this sort of mixed-signals about 126596fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com // clipping. 126696fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com doAA |= element->isAA(); 126745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 126845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com op = SkRegion::kReplace_Op; 126945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 127045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com 12710017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1274ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.orgbool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, 1275ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org bool inverseFilled) { 1276ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // This is for updating the clip conservatively using only bounds 1277ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // information. 1278ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Contract: 1279ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // The current clip must contain the true clip. The true 1280ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // clip is the clip that would have normally been computed 1281ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // by calls to clipPath and clipRRect 1282ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Objective: 1283ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Keep the current clip as small as possible without 1284ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // breaking the contract, using only clip bounding rectangles 1285ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // (for performance). 1286ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org 1287ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // N.B.: This *never* calls back through a virtual on canvas, so subclasses 1288ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // don't have to worry about getting caught in a loop. Thus anywhere 1289ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // we call a virtual method, we explicitly prefix it with 1290ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // SkCanvas:: to be sure to call the base-class. 1291a5d3e77420621c912383c3b22e542d9413d68278skia.committer@gmail.com 1292ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org if (inverseFilled) { 1293ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org switch (op) { 1294ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kIntersect_Op: 1295ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kDifference_Op: 1296ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // These ops can only shrink the current clip. So leaving 1297ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // the clip unchanges conservatively respects the contract. 1298ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->getClipDeviceBounds(NULL); 1299ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kUnion_Op: 1300ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReplace_Op: 1301ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReverseDifference_Op: 1302ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kXOR_Op: 1303ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org { 1304ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // These ops can grow the current clip up to the extents of 1305ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // the input clip, which is inverse filled, so we just set 1306ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // the current clip to the device bounds. 1307ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkRect deviceBounds; 1308ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkIRect deviceIBounds; 1309ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->getDevice()->getGlobalBounds(&deviceIBounds); 1310ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org deviceBounds = SkRect::MakeFromIRect(deviceIBounds); 1311ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); 1312ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // set the clip in device space 1313ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->SkCanvas::setMatrix(SkMatrix::I()); 1314ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org bool result = this->SkCanvas::clipRect(deviceBounds, 1315ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkRegion::kReplace_Op, false); 1316ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->SkCanvas::restore(); //pop the matrix, but keep the clip 1317ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return result; 1318ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1319ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org default: 1320ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkASSERT(0); // unhandled op? 1321ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1322ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } else { 1323ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Not inverse filled 1324ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org switch (op) { 1325ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kIntersect_Op: 1326ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kUnion_Op: 1327ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReplace_Op: 1328ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->SkCanvas::clipRect(bounds, op, false); 1329ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kDifference_Op: 1330ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Difference can only shrink the current clip. 1331ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Leaving clip unchanged conservatively fullfills the contract. 1332ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->getClipDeviceBounds(NULL); 1333ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReverseDifference_Op: 1334ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // To reverse, we swap in the bounds with a replace op. 1335ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // As with difference, leave it unchanged. 1336ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false); 1337ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kXOR_Op: 1338ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Be conservative, based on (A XOR B) always included in (A union B), 1339ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // which is always included in (bounds(A) union bounds(B)) 1340ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false); 1341ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org default: 1342ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkASSERT(0); // unhandled op? 1343ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1344ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1345ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return true; 1346ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org} 1347ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 13495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 13505c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLocalBoundsCompareTypeDirty = true; 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13545c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // todo: signal fClipStack that we have a region, and therefore (I guess) 13555c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // we have to ignore it, and use the region directly? 1356115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com fClipStack.clipDevRect(rgn.getBounds(), op); 13575c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 13580017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(rgn, op); 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1361819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG 1362819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const { 1363819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // construct clipRgn from the clipstack 13641f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com const SkBaseDevice* device = this->getDevice(); 1365ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com if (!device) { 1366ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com SkASSERT(this->getTotalClip().isEmpty()); 1367ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com return; 1368ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com } 1369ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com 1370819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkIRect ir; 1371819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com ir.set(0, 0, device->width(), device->height()); 13720017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip tmpClip(ir); 1373819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 137480214e26c57c5fea954006400852e8999e201923robertphillips@google.com SkClipStack::B2TIter iter(fClipStack); 13758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* element; 13768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com while ((element = iter.next()) != NULL) { 13778182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 13788182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kPath_Type: 13798182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com clipPathHelper(this, 13808182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com &tmpClip, 13818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getPath(), 13828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getOp(), 13838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->isAA()); 13848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 13858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kRect_Type: 13868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getRect().round(&ir); 13878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com tmpClip.op(ir, element->getOp()); 13888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 13898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kEmpty_Type: 13908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com tmpClip.setEmpty(); 13918182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 1392819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1393819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1394819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 13956f8f292aa768869a9e85c314b124875f57504f2creed@google.com#if 0 // enable this locally for testing 1396819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // now compare against the current rgn 1397819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkRegion& rgn = this->getTotalClip(); 13980017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkASSERT(rgn == tmpClip); 139902878b844c5cd3f17d48842da3ccf44a66621501reed@google.com#endif 1400819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1401819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif 1402819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 140390c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const { 140480214e26c57c5fea954006400852e8999e201923robertphillips@google.com SkClipStack::B2TIter iter(fClipStack); 14058182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* element; 14068182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com 14078182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com static const SkRect kEmpty = { 0, 0, 0, 0 }; 14088182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com while ((element = iter.next()) != NULL) { 14098182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 14108182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kPath_Type: 14118182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com visitor->clipPath(element->getPath(), element->getOp(), element->isAA()); 14128182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 14138182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kRect_Type: 14148182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com visitor->clipRect(element->getRect(), element->getOp(), element->isAA()); 14158182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 14168182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kEmpty_Type: 14178182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false); 14188182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 141990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } 142090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } 142190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com} 142290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com 14235c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com/////////////////////////////////////////////////////////////////////////////// 14245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 14253b3e895df6f8ee0f33010367c215944cd16a8334reed@google.comvoid SkCanvas::computeLocalClipBoundsCompareType() const { 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 1427ba09de4c4be66cc07790f23b0f3a925f47340e3ereed@android.com 14283b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (!this->getClipBounds(&r)) { 14293b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com fLocalBoundsCompareType.setEmpty(); 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 14313b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft), 14323b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com SkScalarToCompareType(r.fTop), 14333b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com SkScalarToCompareType(r.fRight), 14343b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com SkScalarToCompareType(r.fBottom)); 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14383b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const { 1439116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 14401607863b608b7db6c813228768ed5d72997bbc82reed@google.com if (!rect.isFinite()) 1441116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org return true; 1442116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 14430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) { 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14478d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (fMCRec->fMatrix->hasPerspective()) { 1448a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 1449a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 1450a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 1451a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 14520017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); 1453a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 14543b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); 1455d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 1456a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 1457a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1458a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1459a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1460a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1461a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1462a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1463a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1464a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1465a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1466a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1467a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14713b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const { 14723b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com return path.isEmpty() || this->quickReject(path.getBounds()); 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1475fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.comstatic inline int pinIntForScalar(int x) { 1476fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com#ifdef SK_SCALAR_IS_FIXED 1477fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com if (x < SK_MinS16) { 1478fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com x = SK_MinS16; 1479fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com } else if (x > SK_MaxS16) { 1480fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com x = SK_MaxS16; 1481fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com } 1482fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com#endif 1483fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com return x; 1484fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com} 1485fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com 14863b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const { 1487bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ibounds; 1488bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!getClipDeviceBounds(&ibounds)) { 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1492d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 1493d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 1494d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 149572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 149672dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 149772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1498d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1499d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1500d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 1502bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkRect r; 15033b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com // adjust it outwards in case we are antialiasing 15043b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com const int inset = 1; 1505fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com 1506fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // SkRect::iset() will correctly assert if we pass a value out of range 1507fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // (when SkScalar==fixed), so we pin to legal values. This does not 1508fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // really returnt the correct answer, but its the best we can do given 1509fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // that we've promised to return SkRect (even though we support devices 1510fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com // that can be larger than 32K in width or height). 1511fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com r.iset(pinIntForScalar(ibounds.fLeft - inset), 1512fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com pinIntForScalar(ibounds.fTop - inset), 1513fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com pinIntForScalar(ibounds.fRight + inset), 1514fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com pinIntForScalar(ibounds.fBottom + inset)); 15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1520bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 15210017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com const SkRasterClip& clip = *fMCRec->fRasterClip; 1522bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (clip.isEmpty()) { 1523bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds) { 1524bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com bounds->setEmpty(); 1525bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1526bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return false; 1527bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1528bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 1529bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (NULL != bounds) { 1530bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com *bounds = clip.getBounds(); 1531bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1532bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return true; 1533bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1534bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1539bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const { 15400017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType; 15410017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isRect()) return kRect_ClipType; 1542bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return kComplex_ClipType; 1543bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1544bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 15460017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->forceGetBW(); 15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15491f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, 1550e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com int width, int height, 1551e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com bool isOpaque) { 15521f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getTopDevice(); 1553cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com if (device) { 1554cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDeviceForSaveLayer(config, width, height, 1555cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com isOpaque); 1556e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1557cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return NULL; 1558e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15611f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, 1562e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com int width, int height, 1563e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com bool isOpaque) { 15641f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 1565e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com if (device) { 1566cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDevice(config, width, height, isOpaque); 1567e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1568e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com return NULL; 1569e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 1570e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com} 1571e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 1572e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 15748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15772a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) { 15782a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com SkDrawIter iter(this); 1579995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org this->predrawNotify(); 15802a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com while (iter.next()) { 15812a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com iter.fDevice->clear(color); 15822a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com } 15832a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com} 15842a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com 15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 1586fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1587fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com} 1588fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com 1589fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) { 1590ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1591ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 15924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) 15938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 15954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPaint(iter, looper.paint()); 15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 16028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1607ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1608ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 1609a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com if (paint.canComputeFastBounds()) { 1610a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com SkRect r; 1611a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com // special-case 2 points (common for drawing a single line) 1612a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com if (2 == count) { 1613a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com r.set(pts[0], pts[1]); 1614a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com } else { 1615a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com r.set(pts, count); 1616a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com } 1617a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com SkRect storage; 16183b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) { 1619a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com return; 1620a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com } 1621fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1622a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com 16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 16248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) 16264b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 16284e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 16298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16304b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16314e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1635ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1636ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 16393b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(paint.computeFastBounds(r, &storage))) { 16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16434b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) 16458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 16474e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawRect(iter, r, looper.paint()); 16488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 16518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1654ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1655ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 16564ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (paint.canComputeFastBounds()) { 16574ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkRect storage; 16584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (this->quickReject(paint.computeFastBounds(oval, &storage))) { 16594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return; 16604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 16614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 1662306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com 166346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type) 166446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 166546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com while (iter.next()) { 166646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com iter.fDevice->drawOval(iter, oval, looper.paint()); 166746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com } 166846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 166946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com LOOPER_END 16704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 16714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 16724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1673ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1674ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 16754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (paint.canComputeFastBounds()) { 16764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkRect storage; 16774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) { 16784ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return; 16794ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 16804ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 16814ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 16824ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (rrect.isRect()) { 16834ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 16844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->SkCanvas::drawRect(rrect.getBounds(), paint); 1685f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org return; 1686f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } else if (rrect.isOval()) { 16874ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 1688f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org this->SkCanvas::drawOval(rrect.getBounds(), paint); 1689f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org return; 16904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 1691f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1692f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type) 1693f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1694f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org while (iter.next()) { 1695f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1696f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } 1697f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1698f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org LOOPER_END 16994ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 17004ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 17014ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 17028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1703ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1704ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 17059364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com if (!path.isFinite()) { 17069364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com return; 17079364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com } 17089364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com 1709fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1710d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect storage; 1711d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 17123b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(paint.computeFastBounds(bounds, &storage))) { 17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1716fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isEmpty()) { 1717fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isInverseFillType()) { 1718fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1719fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 1720fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com return; 1721fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 17264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPath(iter, path, looper.paint()); 17278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17294e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17363d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 17379efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com SkRect bounds = { 17389efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com x, y, 17399efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com x + SkIntToScalar(bitmap.width()), 17409efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com y + SkIntToScalar(bitmap.height()) 17419efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com }; 17429efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (paint) { 17439efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com (void)paint->computeFastBounds(bounds, &bounds); 17449efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com } 17453b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(bounds)) { 17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 17508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 17518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 17529bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com this->internalDrawBitmap(bitmap, matrix, paint); 17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17559987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis 17567112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 1757eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org const SkRect& dst, const SkPaint* paint, 1758eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org DrawBitmapRectFlags flags) { 17598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 176274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 1763ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_LOCKCOUNT_BALANCE(bitmap); 1764ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 17653d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 17669efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com SkRect storage; 17679efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com const SkRect* bounds = &dst; 17689efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (paint) { 17699efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com bounds = &paint->computeFastBounds(dst, &storage); 17709efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com } 17713b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(*bounds)) { 17723d60812865bb034851da777a91413ab584929887reed@google.com return; 17733d60812865bb034851da777a91413ab584929887reed@google.com } 17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17753d60812865bb034851da777a91413ab584929887reed@google.com 177633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com SkLazyPaint lazy; 177733535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com if (NULL == paint) { 177833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com paint = lazy.init(); 17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17807064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com 178133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 17827064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com 178333535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com while (iter.next()) { 1784eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 1785f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 17867064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com 178733535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com LOOPER_END 17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17907112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 1791eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org const SkRect& dst, const SkPaint* paint, 1792eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org DrawBitmapRectFlags flags) { 17939987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 1794eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 17959987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 17969987ec3791336bad6af5cbe513564786b2df55aareed@google.com 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 18009bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com this->internalDrawBitmap(bitmap, matrix, paint); 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18039987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 18049987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkIRect& center, const SkRect& dst, 18059987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkPaint* paint) { 18063d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 180760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com SkRect storage; 180860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com const SkRect* bounds = &dst; 180960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com if (paint) { 181060abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com bounds = &paint->computeFastBounds(dst, &storage); 181160abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com } 18123b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(*bounds)) { 18133d60812865bb034851da777a91413ab584929887reed@google.com return; 18143d60812865bb034851da777a91413ab584929887reed@google.com } 18153d60812865bb034851da777a91413ab584929887reed@google.com } 18163d60812865bb034851da777a91413ab584929887reed@google.com 18179987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t w = bitmap.width(); 18189987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t h = bitmap.height(); 18199987ec3791336bad6af5cbe513564786b2df55aareed@google.com 18209987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkIRect c = center; 18219987ec3791336bad6af5cbe513564786b2df55aareed@google.com // pin center to the bounds of the bitmap 18229987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fLeft = SkMax32(0, center.fLeft); 18239987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fTop = SkMax32(0, center.fTop); 18249987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fRight = SkPin32(center.fRight, c.fLeft, w); 18259987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fBottom = SkPin32(center.fBottom, c.fTop, h); 18269987ec3791336bad6af5cbe513564786b2df55aareed@google.com 18277112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com const SkScalar srcX[4] = { 18287d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 18297112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com }; 18307112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com const SkScalar srcY[4] = { 18317d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 18327112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com }; 18339987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstX[4] = { 18349987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 18359987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 18369987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 18379987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstY[4] = { 18389987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 18399987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 18409987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 184174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 18429987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstX[1] > dstX[2]) { 18439987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 18449987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[2] = dstX[1]; 18459987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 184674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 18479987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstY[1] > dstY[2]) { 18489987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 18499987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[2] = dstY[1]; 18509987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 185174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 18529987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int y = 0; y < 3; y++) { 18537112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com SkRect s, d; 18547112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com 18559987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fTop = srcY[y]; 18569987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fBottom = srcY[y+1]; 18579987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fTop = dstY[y]; 18589987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fBottom = dstY[y+1]; 18599987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int x = 0; x < 3; x++) { 18609987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fLeft = srcX[x]; 18619987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fRight = srcX[x+1]; 18629987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fLeft = dstX[x]; 18639987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fRight = dstX[x+1]; 1864eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org this->internalDrawBitmapRect(bitmap, &s, d, paint, 186531acc11977815402e4ef2681350f8559285bec97robertphillips@google.com kNone_DrawBitmapRectFlag); 18669987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 18679987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 18689987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 18699987ec3791336bad6af5cbe513564786b2df55aareed@google.com 18709987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 18719987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 18729987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 18739987ec3791336bad6af5cbe513564786b2df55aareed@google.com 18749987ec3791336bad6af5cbe513564786b2df55aareed@google.com // Need a device entry-point, so gpu can use a mesh 18759987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapNine(bitmap, center, dst, paint); 18769987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 18779987ec3791336bad6af5cbe513564786b2df55aareed@google.com 1878f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint { 1879f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic: 18801f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 18811f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice::TextFlags flags; 1882f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com if (device->filterTextFlags(paint, &flags)) { 1883a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com SkPaint* newPaint = fLazy.set(paint); 1884f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setFlags(flags.fFlags); 1885f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setHinting(flags.fHinting); 1886f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = newPaint; 1887f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } else { 1888f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = &paint; 1889f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1890f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1891f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1892f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com const SkPaint& paint() const { return *fPaint; } 1893f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1894f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate: 18952c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 18962c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazy; 1897f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com}; 1898f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 189952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 190052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const SkRect& r, SkScalar textSize) { 190117b78946096265d80215a6c946286ecaa35ea7edepoger@google.com if (paint.getStyle() == SkPaint::kFill_Style) { 190252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, paint); 190352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else { 190452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint p(paint); 190517b78946096265d80215a6c946286ecaa35ea7edepoger@google.com p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 190652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, p); 190752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 190852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 190952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 191052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 191152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const char text[], size_t byteLength, 191252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar x, SkScalar y) { 191352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkASSERT(byteLength == 0 || text != NULL); 191452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 191552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com // nothing to draw 191652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (text == NULL || byteLength == 0 || 191752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fClip->isEmpty() || 191852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 191952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 192052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 192152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 192252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar width = 0; 192352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPoint start; 192452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 192552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(0, 0); // to avoid warning 192652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 192752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 192852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com width = paint.measureText(text, byteLength); 192952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 193052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offsetX = 0; 193152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 193252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = SkScalarHalf(width); 193352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 193452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = width; 193552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 193652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(x - offsetX, y); 193752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 193852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 193952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (0 == width) { 194052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 194152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 194252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 194352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com uint32_t flags = paint.getFlags(); 194452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 194552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & (SkPaint::kUnderlineText_Flag | 194652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 194752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar textSize = paint.getTextSize(); 194852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 194952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkRect r; 195052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 195152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fLeft = start.fX; 195252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fRight = start.fX + width; 195352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 195452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kUnderlineText_Flag) { 195552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 195652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 195752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 195852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 195952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 196052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 196152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kStrikeThruText_Flag) { 196252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 196352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 196452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 196552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 196652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 196752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 196852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 196952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 197052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 19718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 19728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 1973ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1974ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 19754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 19768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 19784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1979f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 198052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawTextDecorations(iter, dfp.paint(), 198152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com static_cast<const char*>(text), byteLength, x, y); 19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 19858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 19888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 1989ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1990ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 19914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 19924b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 19938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 19944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 19958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 1996f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19984b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 19994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 2005ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2006ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 20074e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 20084b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 20104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 2012f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 2021ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2022ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 20234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 20274e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com matrix, looper.paint()); 20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20304e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 203356c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID 2034cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.comvoid SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, 2035cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkPoint pos[], const SkPaint& paint, 2036cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkPath& path, const SkMatrix* matrix) { 2037ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2038ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 20394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 2040cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 2041cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com while (iter.next()) { 2042cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, 20434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint(), path, matrix); 2044cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com } 2045cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 20464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 2047cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com} 2048cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com#endif 2049cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 20508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 20518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 20548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 2055ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2056ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 20574e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 20584b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 20608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 20614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com colors, xmode, indices, indexCount, 20624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint()); 20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 20708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 20728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2074845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 20758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 20768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 2078845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 20790baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 20828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2084845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 2088845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 20890baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 20908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 20928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 20964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 20998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 21028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 21038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 21044b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 21134b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 21168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 21218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 21238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 21364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->drawOval(r, paint); 21378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 21428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 21438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 21443b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(paint.computeFastBounds(r, &storage))) { 21458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 21468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21484ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkRRect rrect; 21494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com rrect.setRectXY(r, rx, ry); 21504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->drawRRect(rrect, paint); 21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 21578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 21628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 21658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 21758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 21768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 21784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 21808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2183f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 2184f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 21878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2193d642329293cce602ac24df8f585c14a98795da87reed@google.com SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 21988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 21998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 22078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22091f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const { 22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 22158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 22188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 22198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 222820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com 222920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com/////////////////////////////////////////////////////////////////////////////// 223020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com 223120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.comSkCanvas::ClipVisitor::~ClipVisitor() { } 2232