SkCanvas.cpp revision c3bd8af6d5722e854feca70c40d92f4954c5b67b
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" 2297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 2452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h" 25a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU 29644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h" 30644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif 31644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org 32da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing... 33da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT 3415e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gLayerCounter; 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gRecCounter; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int gCanvasCounter; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_layer() 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_layer() 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_rec() 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_rec() 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define inc_canvas() 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define dec_canvas() 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 58ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#ifdef SK_DEBUG 59ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#include "SkPixelRef.h" 60ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 61f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com/* 62f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * Some pixelref subclasses can support being "locked" from another thread 63f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * during the lock-scope of skia calling them. In these instances, this balance 64f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * check will fail, but may not be indicative of a problem, so we allow a build 65f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * flag to disable this check. 66f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * 67f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * Potentially another fix would be to have a (debug-only) virtual or flag on 68f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * pixelref, which could tell us at runtime if this check is valid. That would 69f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com * eliminate the need for this heavy-handed build check. 70f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com */ 71f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK 72f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.comclass AutoCheckLockCountBalance { 73f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.compublic: 74f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ } 75f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com}; 76f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#else 77ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckLockCountBalance { 78ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic: 79ea033606a06d05d2d42aa7118409fee798e53167reed@google.com AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) { 80ea033606a06d05d2d42aa7118409fee798e53167reed@google.com fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0; 81ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 82ea033606a06d05d2d42aa7118409fee798e53167reed@google.com ~AutoCheckLockCountBalance() { 83ea033606a06d05d2d42aa7118409fee798e53167reed@google.com const int count = fPixelRef ? fPixelRef->getLockCount() : 0; 84ea033606a06d05d2d42aa7118409fee798e53167reed@google.com SkASSERT(count == fLockCount); 85ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 86ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 87ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate: 88ea033606a06d05d2d42aa7118409fee798e53167reed@google.com const SkPixelRef* fPixelRef; 89ea033606a06d05d2d42aa7118409fee798e53167reed@google.com int fLockCount; 90ea033606a06d05d2d42aa7118409fee798e53167reed@google.com}; 91f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#endif 92ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 93ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckNoSetContext { 94ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic: 95ea033606a06d05d2d42aa7118409fee798e53167reed@google.com AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) { 96ea033606a06d05d2d42aa7118409fee798e53167reed@google.com this->assertNoSetContext(fPaint); 97ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 98ea033606a06d05d2d42aa7118409fee798e53167reed@google.com ~AutoCheckNoSetContext() { 99ea033606a06d05d2d42aa7118409fee798e53167reed@google.com this->assertNoSetContext(fPaint); 100ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 101ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 102ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate: 103ea033606a06d05d2d42aa7118409fee798e53167reed@google.com const SkPaint& fPaint; 104ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 105ea033606a06d05d2d42aa7118409fee798e53167reed@google.com void assertNoSetContext(const SkPaint& paint) { 106ea033606a06d05d2d42aa7118409fee798e53167reed@google.com SkShader* s = paint.getShader(); 107ea033606a06d05d2d42aa7118409fee798e53167reed@google.com if (s) { 108ea033606a06d05d2d42aa7118409fee798e53167reed@google.com SkASSERT(!s->setContextHasBeenCalled()); 109ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 110ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 111ea033606a06d05d2d42aa7118409fee798e53167reed@google.com}; 112ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 113ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap) 114ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint) 115ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 116ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#else 117ea033606a06d05d2d42aa7118409fee798e53167reed@google.com #define CHECK_LOCKCOUNT_BALANCE(bitmap) 118ea033606a06d05d2d42aa7118409fee798e53167reed@google.com #define CHECK_SHADER_NOSETCONTEXT(paint) 119ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#endif 120ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 1212c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint; 1222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org 12397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() { 12497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com if (fSurfaceBase) { 125c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); 12697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com } 12797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com} 12897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1311f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/* This is the record we keep for each SkBaseDevice that the user installs. 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The clip/matrix/proc are fields that reflect the top of the save/restore 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stack. Whenever the canvas changes, it marks a dirty flag, and then before 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com these are used (assuming we're not on a layer) we rebuild these cache 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com values: they reflect the top of the save stack, but translated and clipped 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com by the device's XY offset and bitmap-bounds. 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM { 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fNext; 1401f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* fDevice; 141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip fClip; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* fMatrix; 1436f8f292aa768869a9e85c314b124875f57504f2creed@google.com SkPaint* fPaint; // may be null (in the future) 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1451f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas) 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fNext(NULL) { 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != device) { 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->ref(); 14940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com device->onAttachToCanvas(canvas); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com fDevice = device; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 15388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com ~DeviceCM() { 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fDevice) { 15740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com fDevice->onDetachFromCanvas(); 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice->unref(); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com SkDELETE(fPaint); 16188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 1624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 163045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkClipStack& clipStack, SkRasterClip* updateClip) { 1656f8f292aa768869a9e85c314b124875f57504f2creed@google.com int x = fDevice->getOrigin().x(); 1666f8f292aa768869a9e85c314b124875f57504f2creed@google.com int y = fDevice->getOrigin().y(); 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = fDevice->width(); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = fDevice->height(); 1694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x | y) == 0) { 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &totalMatrix; 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = totalClip; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = totalMatrix; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.postTranslate(SkIntToScalar(-x), 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(-y)); 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 1784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com totalClip.translate(-x, -y, &fClip); 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // intersect clip, but don't translate it (yet) 1854b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (updateClip) { 187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::kDifference_Op); 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 1913fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 1923fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fClip.isEmpty()) { 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect deviceR; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com deviceR.set(0, 0, width, height); 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(deviceR.contains(fClip.getBounds())); 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 200f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 201f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2030e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com SkMatrix fMatrixStorage; 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This is the record we keep for each save/restore level in the stack. 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Since a level optionally copies the matrix and/or stack, we have pointers 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for these fields. If the value is copied for this level, the copy is 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stored in the ...Storage field, and the pointer points to that. If the 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value is not copied for this level, we ignore ...Storage, and just point 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com at the corresponding value in the previous level in the stack. 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec { 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* fNext; 2166c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org int fFlags; 2170017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 2180017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec 2190017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkDrawFilter* fFilter; // the current filter (or null) 2204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* fLayer; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* If there are any layers in the stack, this points to the top-most 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com one that is at or below this level in the stack (so we know what 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap/device to draw into from this level. This value is NOT 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reference counted, since the real owner is either our fLayer field, 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com or a previous one in a lower level.) 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 22888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com DeviceCM* fTopLayer; 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2306c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org MCRec(const MCRec* prev, int flags) : fFlags(flags) { 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != prev) { 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kMatrix_SaveFlag) { 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage = *prev->fMatrix; 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = prev->fMatrix; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkCanvas::kClip_SaveFlag) { 2400017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClipStorage = *prev->fRasterClip; 2410017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = &fRasterClipStorage; 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = prev->fRasterClip; 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = prev->fFilter; 24782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeRef(fFilter); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = prev->fTopLayer; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no prev 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrixStorage.reset(); 2524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = &fMatrixStorage; 2540017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fRasterClip = &fRasterClipStorage; 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFilter = NULL; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTopLayer = NULL; 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLayer = NULL; 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't bother initializing fNext 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_rec(); 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~MCRec() { 26482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fFilter); 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fLayer); 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_rec(); 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2700017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkMatrix fMatrixStorage; 2710017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip fRasterClipStorage; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw { 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2768a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 2774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com canvas = canvas->canvasForDrawIter(); 2788a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fCanvas = canvas; 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com canvas->updateDeviceCMCache(); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com fClipStack = &canvas->fClipStack; 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = canvas->getBounder(); 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = canvas->fMCRec->fTopLayer; 2848a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com fSkipEmptyClips = skipEmptyClips; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool next() { 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip over recs with empty clips 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fSkipEmptyClips) { 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = fCurrLayer->fNext; 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 295f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com const DeviceCM* rec = fCurrLayer; 296f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com if (rec && rec->fDevice) { 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix = rec->fMatrix; 299045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 300045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = &rec->fClip; 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDevice = rec->fDevice; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBitmap = &fDevice->accessBitmap(true); 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = rec->fPaint; 304f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrLayer = rec->fNext; 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->setClip(fClip); 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fCurrLayer may be NULL now 311199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 3171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* getDevice() const { return fDevice; } 3186f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getX() const { return fDevice->getOrigin().x(); } 3196f8f292aa768869a9e85c314b124875f57504f2creed@google.com int getY() const { return fDevice->getOrigin().y(); } 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& getMatrix() const { return *fMatrix; } 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion& getClip() const { return *fClip; } 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* getPaint() const { return fPaint; } 3236f8f292aa768869a9e85c314b124875f57504f2creed@google.com 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas* fCanvas; 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const DeviceCM* fCurrLayer; 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; // May be null. 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBool8 fSkipEmptyClips; 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkDraw INHERITED; 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper { 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3378926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, 33878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bool skipLayerForImageFilter = false, 33978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL) : 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()); 35178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org (void)canvas->internalSaveLayer(bounds, &tmp, 3528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkCanvas::kARGB_ClipLayer_SaveFlag, true); 3538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // we'll clear the imageFilter for the actual draws in next(), so 3548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // it will only be applied during the restore(). 3558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fDoClearImageFilter = true; 3568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 3584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com if (fLooper) { 3594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fLooper->init(canvas); 360129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fIsSimple = false; 361129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } else { 362129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com // can we be marked as simple? 363129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fIsSimple = !fFilter && !fDoClearImageFilter; 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 36674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com ~AutoDrawLooper() { 3688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (fDoClearImageFilter) { 3698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com fCanvas->internalRestore(); 3708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 3714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fCanvas->getSaveCount() == fSaveCount); 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 37374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com const SkPaint& paint() const { 3754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkASSERT(fPaint); 3764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return *fPaint; 3774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 37874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 379129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com bool next(SkDrawFilter::Type drawType) { 380129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fDone) { 381129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return false; 382129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } else if (fIsSimple) { 383129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fDone = true; 384129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fPaint = &fOrigPaint; 385129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return !fPaint->nothingToDraw(); 386129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } else { 387129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return this->doNext(drawType); 388129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 389fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 39074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3922c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazyPaint; 3932c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkCanvas* fCanvas; 3942c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint& fOrigPaint; 3952c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawLooper* fLooper; 3962c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkDrawFilter* fFilter; 3972c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 3982c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org int fSaveCount; 3998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com bool fDoClearImageFilter; 4002c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org bool fDone; 401129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com bool fIsSimple; 402129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com 403129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com bool doNext(SkDrawFilter::Type drawType); 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 406129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 407632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fPaint = NULL; 408129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com SkASSERT(!fIsSimple); 409129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com SkASSERT(fLooper || fFilter || fDoClearImageFilter); 410632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com 411129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com SkPaint* paint = fLazyPaint.set(fOrigPaint); 4128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 413129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fDoClearImageFilter) { 414129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com paint->setImageFilter(NULL); 415129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 4168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 417129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fLooper && !fLooper->next(fCanvas, paint)) { 418129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fDone = true; 419129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com return false; 420129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 421129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (fFilter) { 422971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com if (!fFilter->filter(paint, drawType)) { 423971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com fDone = true; 424971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com return false; 425971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com } 426129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (NULL == fLooper) { 427129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com // no looper means we only draw once 428632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com fDone = true; 429632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com } 430129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com } 431129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com fPaint = paint; 4328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 433129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com // if we only came in here for the imagefilter, mark us as done 434129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com if (!fLooper && !fFilter) { 4354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fDone = true; 4364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 4374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 438632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com // call this after any possible paint modifiers 439632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com if (fPaint->nothingToDraw()) { 4404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com fPaint = NULL; 4414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return false; 4424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com } 4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com return true; 4444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com} 4454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Stack helper for managing a SkBounder. In the destructor, if we were 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com given a bounder, we call its commit() method, signifying that we are 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com done accumulating bounds for that draw. 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit { 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBounderCommit() { 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != fBounder) { 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder->commit(); 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 461e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit) 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 47478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds) \ 47597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com this->predrawNotify(); \ 47678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org AutoDrawLooper looper(this, paint, false, bounds); \ 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; 487c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBounds.setEmpty(); 488c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = 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() 508e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 509e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{ 5108d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org inc_canvas(); 511ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com 5128d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org this->init(NULL); 5138d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org} 5148d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org 515e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.orgSkCanvas::SkCanvas(int width, int height) 516e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 517e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{ 518e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org inc_canvas(); 519ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com 520e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org SkBitmap bitmap; 521e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org bitmap.setConfig(SkBitmap::kNo_Config, width, height); 522e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); 523e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org} 524e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org 5251f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkCanvas::SkCanvas(SkBaseDevice* device) 526e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 527e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{ 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->init(device); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap) 534e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 535e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{ 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inc_canvas(); 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5381f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() { 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // free up the contents of our deque 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restoreToCount(1); // restore everything but the last 544b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org SkASSERT(0 == fSaveLayerCount); 5457c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); // restore the last, since we're going away 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5488d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org SkSafeUnref(fBounder); 54974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org SkDELETE(fMetaData); 550b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dec_canvas(); 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) { 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fBounder, bounder); 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder; 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const { 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fFilter; 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return filter; 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 56874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() { 56974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org // metadata users are rare, so we lazily allocate it. If that changes we 57074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org // can decide to just make it a field in the device (rather than a ptr) 57174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org if (NULL == fMetaData) { 57274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org fMetaData = new SkMetaData; 57374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org } 57474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org return *fMetaData; 57574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org} 57674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 579bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() { 5801f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 581bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org if (device) { 582bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org device->flush(); 583bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org } 584bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org} 585bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org 586210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.comSkISize SkCanvas::getDeviceSize() const { 5871f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* d = this->getDevice(); 588210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 589210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com} 590210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com 5911f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const { 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 593c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com MCRec* rec = (MCRec*) fMCStack.front(); 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec->fLayer->fDevice; 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5981f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 5990b53d59a24f667350b4282f88470713902409030reed@google.com if (updateMatrixClip) { 6000b53d59a24f667350b4282f88470713902409030reed@google.com const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 6010b53d59a24f667350b4282f88470713902409030reed@google.com } 6029266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com return fMCRec->fTopLayer->fDevice; 6039266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com} 6049266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com 6051f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::setDevice(SkBaseDevice* device) { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return root device 6074c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com SkDeque::F2BIter iter(fMCStack); 6084c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com MCRec* rec = (MCRec*)iter.next(); 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec && rec->fLayer); 6101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* rootDevice = rec->fLayer->fDevice; 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice == device) { 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device) { 61740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com device->onAttachToCanvas(this); 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rootDevice) { 62040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com rootDevice->onDetachFromCanvas(); 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rootDevice = device; 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 6274b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Now we update our initial region to have the bounds of the new device, 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com and then intersect all of the clips in our stack with these bounds, 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com to ensure that we can't draw outside of the device's bounds (and trash 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memory). 6324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NOTE: this is only a partial-fix, since if the new device is larger than 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the previous one, we don't know how to "enlarge" the clips in our stack, 6354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com so drawing may be artificially restricted. Without keeping a history of 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reconstruct the correct clips, so this approximation will have to do. 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The caller really needs to restore() back to the base if they want to 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com accurately take advantage of the new device bounds. 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 64242aea289cbf801997b653a906a37a7f7e948b645reed@google.com SkIRect bounds; 64342aea289cbf801997b653a906a37a7f7e948b645reed@google.com if (device) { 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(0, 0, device->width(), device->height()); 64542aea289cbf801997b653a906a37a7f7e948b645reed@google.com } else { 64642aea289cbf801997b653a906a37a7f7e948b645reed@google.com bounds.setEmpty(); 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 64842aea289cbf801997b653a906a37a7f7e948b645reed@google.com // now jam our 1st clip to be bounds, and intersect the rest with that 64942aea289cbf801997b653a906a37a7f7e948b645reed@google.com rec->fRasterClip->setRect(bounds); 65042aea289cbf801997b653a906a37a7f7e948b645reed@google.com while ((rec = (MCRec*)iter.next()) != NULL) { 65142aea289cbf801997b653a906a37a7f7e948b645reed@google.com (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); 65242aea289cbf801997b653a906a37a7f7e948b645reed@google.com } 65342aea289cbf801997b653a906a37a7f7e948b645reed@google.com 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return device; 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6576850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.combool SkCanvas::readPixels(SkBitmap* bitmap, 6586850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com int x, int y, 6596850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com Config8888 config8888) { 6601f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 66151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (!device) { 66251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 66351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 6646850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com return device->readPixels(bitmap, x, y, config8888); 66551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 66651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 667c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 6681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 669ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com if (!device) { 670ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com return false; 671ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com } 67274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 673daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com SkIRect bounds; 674c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bounds.set(0, 0, device->width(), device->height()); 675daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com if (!bounds.intersect(srcRect)) { 676daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com return false; 677c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } 678c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com 679c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com SkBitmap tmp; 680c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), 681c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bounds.height()); 682c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) { 683c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com bitmap->swap(tmp); 684c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com return true; 685c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com } else { 68651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com return false; 68751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 68851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 68951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 690d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y, 691d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com Config8888 config8888) { 6921f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getDevice(); 69351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com if (device) { 694405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()), 695405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) { 696405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com device->accessBitmap(true); 697405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com device->writePixels(bitmap, x, y, config8888); 698405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com } 69951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com } 70051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com} 70151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com 7024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() { 7034370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com return this; 7044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com} 7054370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() { 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDeviceCMDirty) { 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& totalMatrix = this->getTotalMatrix(); 711045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& totalClip = *fMCRec->fRasterClip; 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fTopLayer; 7134b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == layer->fNext) { // only one layer 71546799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 717045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip(totalClip); 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 71946799cd9f0bded51a189d77731b25af159ab4609reed@google.com layer->updateMC(totalMatrix, clip, fClipStack, &clip); 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((layer = layer->fNext) != NULL); 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = false; 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) { 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int saveCount = this->getSaveCount(); // record this before the actual save 7304b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MCRec* newTop = (MCRec*)fMCStack.push_back(); 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new (newTop) MCRec(fMCRec, flags); // balanced in restore() 7334b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newTop->fNext = fMCRec; 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = newTop; 7364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 7376c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org if (SkCanvas::kClip_SaveFlag & flags) { 7386c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org fClipStack.save(); 7396c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org } 7405c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return saveCount; 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) { 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call shared impl 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->internalSave(flags); 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config) 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config) 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK (1 << SkBitmap::kA8_Config) 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas, 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds, 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::SaveFlags flags, 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool* isOpaque) { 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // loop through and union all the configs we may draw into 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t configMask = 0; 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 7641f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = canvas->getLayerDevice(i); 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (device->intersects(bounds)) 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask |= 1 << device->config(); 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if the caller wants alpha or fullcolor, we can't return 565 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::kHasAlphaLayer_SaveFlag)) 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com configMask &= ~C16MASK; 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (configMask) { 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C8MASK: // if we only have A8, return that 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kA8_Config; 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case C16MASK: // if we only have 565, return that 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kRGB_565_Config; 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkBitmap::kARGB_8888_Config; // default answer 7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 793a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 794c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkIRect* intersection, const SkImageFilter* imageFilter) { 795bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect clipBounds; 796c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org SkRegion::Op op = SkRegion::kIntersect_Op; 797bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!this->getClipDeviceBounds(&clipBounds)) { 798a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 799f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 800c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org 801c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org if (imageFilter) { 802c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds); 803c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org // Filters may grow the bounds beyond the device bounds. 804c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org op = SkRegion::kReplace_Op; 805c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org } 806bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ir; 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 8094b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getTotalMatrix().mapRect(&r, *bounds); 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.roundOut(&ir); 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the layer's bounds are clipped out 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!ir.intersect(clipBounds)) { 814bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds_affects_clip(flags)) { 8150017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fMCRec->fRasterClip->setEmpty(); 816bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 817a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no user bounds, so just use the clip 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir = clipBounds; 8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 823c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org fClipStack.clipDevRect(ir, op); 824a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // early exit if the clip is now empty 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bounds_affects_clip(flags) && 827c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org !fMCRec->fRasterClip->op(ir, op)) { 828a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return false; 829a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org } 830a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 831a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org if (intersection) { 832a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org *intersection = ir; 833a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org } 834a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org return true; 835a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org} 836a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 837a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 838a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SaveFlags flags) { 8398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return this->internalSaveLayer(bounds, paint, flags, false); 8408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com} 8418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 84276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comstatic SkBaseDevice* createCompatibleDevice(SkCanvas* canvas, 84376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com SkBitmap::Config config, 84476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com int width, int height, 84576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com bool isOpaque) { 84676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com SkBaseDevice* device = canvas->getDevice(); 84776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com if (device) { 84876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com return device->createCompatibleDevice(config, width, height, isOpaque); 84976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com } else { 85076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com return NULL; 85176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com } 85276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com} 85376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com 8548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, 8558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SaveFlags flags, bool justForImageFilter) { 856a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org // do this before we create the layer. We don't call the public save() since 857a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org // that would invoke a possibly overridden virtual 858a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org int count = this->internalSave(flags); 859a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 860a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org fDeviceCMDirty = true; 861a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org 862a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org SkIRect ir; 863c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) { 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 867b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com // Kill the imagefilter if our device doesn't allow it 868b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkLazyPaint lazyP; 869b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com if (paint && paint->getImageFilter()) { 870b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 8718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (justForImageFilter) { 8728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // early exit if the layer was just for the imageFilter 8738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return count; 8748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 875b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com SkPaint* p = lazyP.set(*paint); 876b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com p->setImageFilter(NULL); 877b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com paint = p; 878b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com } 879b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com } 880b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isOpaque; 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8841f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device; 88576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com if (paint && paint->getImageFilter()) { 88676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com device = createCompatibleDevice(this, config, ir.width(), ir.height(), 88776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com isOpaque); 88876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } else { 88976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com device = this->createLayerDevice(config, ir.width(), ir.height(), 89076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com isOpaque); 89176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 892e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com if (NULL == device) { 893e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com SkDebugf("Unable to create device for layer."); 894e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com return count; 895e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com } 896e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 8976f8f292aa768869a9e85c314b124875f57504f2creed@google.com device->setOrigin(ir.fLeft, ir.fTop); 89840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this)); 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device->unref(); 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com layer->fNext = fMCRec->fTopLayer; 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = layer; 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 905b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount += 1; 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SaveFlags flags) { 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, NULL, flags); 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmpPaint; 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpPaint.setAlpha(alpha); 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->saveLayer(bounds, &tmpPaint, flags); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() { 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for underflow 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCStack.count() > 1) { 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->internalRestore(); 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() { 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMCStack.count() != 0); 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 931c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9336c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) { 9346c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org fClipStack.restore(); 9356c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org } 9366c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org 93788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com // reserve our layer (if any) 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DeviceCM* layer = fMCRec->fLayer; // may be null 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now detach it from fMCRec so we can pop(). Gets freed after its drawn 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fLayer = NULL; 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the normal restore() 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->~MCRec(); // balanced in save() 9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCStack.pop_back(); 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec = (MCRec*)fMCStack.back(); 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* Time to draw the layer's offscreen. We can't call the public drawSprite, 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com since if we're being recorded, we don't want to record this (the 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com recorder will have already recorded the restore). 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != layer) { 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (layer->fNext) { 9536f8f292aa768869a9e85c314b124875f57504f2creed@google.com const SkIPoint& origin = layer->fDevice->getOrigin(); 9548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 9558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com layer->fPaint); 9568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // reset this, since internalDrawDevice will have set it to true 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 9587c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 959b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org SkASSERT(fSaveLayerCount > 0); 960b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org fSaveLayerCount -= 1; 9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(layer); 96388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com } 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const { 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCStack.count(); 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) { 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // sanity check 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 1) { 9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = 1; 9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 97574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 976b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com int n = this->getSaveCount() - count; 977b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com for (int i = 0; i < n; ++i) { 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->restore(); 9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9827c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const { 983b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org return fSaveLayerCount > 0; 9847c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com} 9857c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com 98676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::newSurface(const SkImageInfo& info) { 98776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com return this->onNewSurface(info); 98876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com} 98976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com 99076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) { 99176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com SkBaseDevice* dev = this->getDevice(); 99276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com return dev ? dev->newSurface(info) : NULL; 99376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com} 99476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com 995c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const { 996c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org SkBaseDevice* dev = this->getDevice(); 997c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (dev) { 998c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return dev->imageInfo(); 999c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } else { 1000c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org // TODO: need a real unknown for alphatype it seems. 1001c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org SkAlphaType unknownAlphaType = kIgnore_SkAlphaType; 1002c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return SkImageInfo::Make(0, 0, kUnknown_SkColorType, unknownAlphaType); 1003c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 1004c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 1005c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 1006c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1007c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return this->onPeekPixels(info, rowBytes); 1008c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 1009c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 1010c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) { 1011c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org SkBaseDevice* dev = this->getDevice(); 1012c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return dev ? dev->peekPixels(info, rowBytes) : NULL; 1013c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 1014c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 1015c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) { 1016c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org fAddr = canvas->peekPixels(&fInfo, &fRowBytes); 1017c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (NULL == fAddr) { 1018c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org fInfo = canvas->imageInfo(); 1019c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (kUnknown_SkColorType == fInfo.colorType() || 1020c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org !fBitmap.allocPixels(fInfo)) 1021c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org { 1022c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return; // failure, fAddr is NULL 1023c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 1024c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org fBitmap.lockPixels(); 1025c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (!canvas->readPixels(&fBitmap, 0, 0)) { 1026c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return; // failure, fAddr is NULL 1027c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 1028c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org fAddr = fBitmap.getPixels(); 1029c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org fRowBytes = fBitmap.rowBytes(); 1030c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 1031c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org SkASSERT(fAddr); // success 1032c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 1033c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 1034c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const { 1035c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (fAddr) { 1036c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes, 1037c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org NULL, NULL); 1038c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } else { 1039c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org bitmap->reset(); 1040c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return false; 1041c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 1042c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 1043c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10469bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, const SkPaint* paint) { 104850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org if (bitmap.drawsNothing()) { 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10522c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint lazy; 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 10542c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org paint = lazy.init(); 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10569bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 10579bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com SkDEBUGCODE(bitmap.validate();) 10589bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com CHECK_LOCKCOUNT_BALANCE(bitmap); 10599bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 106078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect storage; 106178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL; 106278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org if (paint && paint->canComputeFastBounds()) { 106378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bitmap.getBounds(&storage); 106478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org matrix.mapRect(&storage); 106578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bounds = &paint->computeFastBounds(storage, &storage); 106678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org } 106778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org 106878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 10699bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 10709bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com while (iter.next()) { 10719bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 10729bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com } 10739bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com 10749bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com LOOPER_END 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10771f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 10788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com const SkPaint* paint) { 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint tmp; 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setDither(true); 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &tmp; 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 10858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 10871f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* dstDev = iter.fDevice; 108876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com paint = &looper.paint(); 108976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkImageFilter* filter = paint->getImageFilter(); 109076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 10918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (filter && !dstDev->canHandleImageFilter(filter)) { 10929c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org SkDeviceImageFilterProxy proxy(dstDev); 109376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkBitmap dst; 10946776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org SkIPoint offset = SkIPoint::Make(0, 0); 1095b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com const SkBitmap& src = srcDev->accessBitmap(false); 1096fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org SkMatrix matrix = *iter.fMatrix; 1097fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 10986776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org if (filter->filterImage(&proxy, src, matrix, &dst, &offset)) { 10995efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com SkPaint tmpUnfiltered(*paint); 11005efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered.setImageFilter(NULL); 11016776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 11026776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org tmpUnfiltered); 110376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 110476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } else { 1105b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 110676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com } 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 11128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com const SkPaint* paint) { 111350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org if (bitmap.drawsNothing()) { 11148926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com return; 11158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 111650b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org SkDEBUGCODE(bitmap.validate();) 111750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org CHECK_LOCKCOUNT_BALANCE(bitmap); 1118fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkPaint tmp; 11208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (NULL == paint) { 11218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint = &tmp; 11228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 1123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1125fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com while (iter.next()) { 11278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com paint = &looper.paint(); 11288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkImageFilter* filter = paint->getImageFilter(); 11298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 11308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 11319c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org SkDeviceImageFilterProxy proxy(iter.fDevice); 11328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com SkBitmap dst; 11336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org SkIPoint offset = SkIPoint::Make(0, 0); 1134fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org SkMatrix matrix = *iter.fMatrix; 1135fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); 11366776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org if (filter->filterImage(&proxy, bitmap, matrix, &dst, &offset)) { 11375efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com SkPaint tmpUnfiltered(*paint); 11385efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered.setImageFilter(NULL); 11396776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 11405efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com tmpUnfiltered); 11418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 11428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } else { 11438926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 11448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 11458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com } 11468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com LOOPER_END 11478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com} 11488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////// 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) { 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1153c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preTranslate(dx, dy); 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) { 11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1159c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preScale(sx, sy); 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) { 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1165c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preRotate(degrees); 11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) { 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1171c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preSkew(sx, sy); 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) { 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1177c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMCRec->fMatrix->preConcat(matrix); 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) { 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1183c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fMCRec->fMatrix = matrix; 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() { 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 11914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setMatrix(matrix); 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1198c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1199da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT 1200da17f758442f16747af39f8fbaed9c097048519creed@google.com if (SkRegion::kIntersect_Op == op) { 1201da17f758442f16747af39f8fbaed9c097048519creed@google.com if (fMCRec->fRasterClip->isEmpty()) { 1202da17f758442f16747af39f8fbaed9c097048519creed@google.com return false; 1203da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1204da17f758442f16747af39f8fbaed9c097048519creed@google.com 12053b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(rect)) { 1206da17f758442f16747af39f8fbaed9c097048519creed@google.com fDeviceCMDirty = true; 1207c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 1208da17f758442f16747af39f8fbaed9c097048519creed@google.com 1209da17f758442f16747af39f8fbaed9c097048519creed@google.com fClipStack.clipEmpty(); 1210da17f758442f16747af39f8fbaed9c097048519creed@google.com return fMCRec->fRasterClip->setEmpty(); 1211da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1212da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1213da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif 1214da17f758442f16747af39f8fbaed9c097048519creed@google.com 12155c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 12165c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1218c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 12198f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com doAA &= fAllowSoftClip; 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fMCRec->fMatrix->rectStaysRect()) { 1222123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com // for these simpler matrices, we can stay a rect even after applying 122398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the matrix. This means we don't have to a) make a path, and b) tell 122498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // the region code to scan-convert the path, only to discover that it 122598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // is really just a rect. 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMCRec->fMatrix->mapRect(&r, rect); 12290017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevRect(r, op, doAA); 12300017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(r, op, doAA); 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1232123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com // since we're rotated or some such thing, we convert the rect to a path 123398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // and clip against that, since it can handle any matrix. However, to 123498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // avoid recursion in the case where we are subclassed (e.g. Pictures) 123598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com // we explicitly call "our" version of clipPath. 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addRect(rect); 1239c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com return this->SkCanvas::clipPath(path, op, doAA); 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 1244c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com const SkPath& devPath, SkRegion::Op op, bool doAA) { 1245759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // base is used to limit the size (and therefore memory allocation) of the 1246759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // region that results from scan converting devPath. 1247759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com SkRegion base; 1248759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com 1249819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kIntersect_Op == op) { 1250759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // since we are intersect, we can do better (tighter) with currRgn's 1251759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // bounds, than just using the device. However, if currRgn is complex, 1252759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com // our region blitter may hork, so we do that case in two steps. 12530017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (currClip->isRect()) { 1254b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org // FIXME: we should also be able to do this when currClip->isBW(), 1255b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org // but relaxing the test above triggers GM asserts in 1256b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org // SkRgnBuilder::blitH(). We need to investigate what's going on. 1257b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org return currClip->setPath(devPath, currClip->bwRgn(), doAA); 1258759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } else { 12590017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com base.setRect(currClip->getBounds()); 12600017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 12610017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 12620017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 1263759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com } 1264819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 12651f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com const SkBaseDevice* device = canvas->getDevice(); 1266ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com if (!device) { 1267ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com return currClip->setEmpty(); 1268ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com } 1269ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com 1270a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org base.setRect(0, 0, device->width(), device->height()); 1271819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 1272819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com if (SkRegion::kReplace_Op == op) { 12730017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->setPath(devPath, base, doAA); 1274819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } else { 12750017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip clip; 12760017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com clip.setPath(devPath, base, doAA); 12770017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return currClip->op(clip, op); 1278819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1279819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1280819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1281819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 12824ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.combool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 12834ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (rrect.isRect()) { 12844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 12854ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA); 12864ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } else { 12874ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkPath path; 12884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com path.addRRect(rrect); 12894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 12904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return this->SkCanvas::clipPath(path, op, doAA); 12914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 12924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 12934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 1294c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1295da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT 1296da17f758442f16747af39f8fbaed9c097048519creed@google.com if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1297da17f758442f16747af39f8fbaed9c097048519creed@google.com if (fMCRec->fRasterClip->isEmpty()) { 1298da17f758442f16747af39f8fbaed9c097048519creed@google.com return false; 1299da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1300fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 13013b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(path.getBounds())) { 1302da17f758442f16747af39f8fbaed9c097048519creed@google.com fDeviceCMDirty = true; 1303c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 1304fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1305da17f758442f16747af39f8fbaed9c097048519creed@google.com fClipStack.clipEmpty(); 1306da17f758442f16747af39f8fbaed9c097048519creed@google.com return fMCRec->fRasterClip->setEmpty(); 1307da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1308da17f758442f16747af39f8fbaed9c097048519creed@google.com } 1309da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif 1310da17f758442f16747af39f8fbaed9c097048519creed@google.com 13115c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 13125c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1314c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 13158f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com doAA &= fAllowSoftClip; 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath devPath; 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.transform(*fMCRec->fMatrix, &devPath); 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1320fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // Check if the transfomation, or the original path itself 1321fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // made us empty. Note this can also happen if we contained NaN 1322fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // values. computing the bounds detects this, and will set our 1323fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1324fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com if (devPath.getBounds().isEmpty()) { 1325fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // resetting the path will remove any NaN or other wanky values 1326fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com // that might upset our scan converter. 1327fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com devPath.reset(); 1328fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com } 1329fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com 13305c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // if we called path.swap() we could avoid a deep copy of this path 13310017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com fClipStack.clipDevPath(devPath, op, doAA); 13325c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 133345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (fAllowSimplifyClip) { 133445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com devPath.reset(); 133545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com devPath.setFillType(SkPath::kInverseEvenOdd_FillType); 133645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com const SkClipStack* clipStack = getClipStack(); 133745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); 133845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com const SkClipStack::Element* element; 133945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com while ((element = iter.next())) { 134045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkClipStack::Element::Type type = element->getType(); 134145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (type == SkClipStack::Element::kEmpty_Type) { 134245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com continue; 134345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 134445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkPath operand; 134545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (type == SkClipStack::Element::kRect_Type) { 134645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com operand.addRect(element->getRect()); 134745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } else if (type == SkClipStack::Element::kPath_Type) { 134845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com operand = element->getPath(); 134945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } else { 135045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkDEBUGFAIL("Unexpected type."); 135145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 135245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com SkRegion::Op elementOp = element->getOp(); 135345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com if (elementOp == SkRegion::kReplace_Op) { 135445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com devPath = operand; 135545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } else { 135645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com Op(devPath, operand, (SkPathOp) elementOp, &devPath); 135745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 135896fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com // if the prev and curr clips disagree about aa -vs- not, favor the aa request. 135996fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com // perhaps we need an API change to avoid this sort of mixed-signals about 136096fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com // clipping. 136196fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com doAA |= element->isAA(); 136245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 136345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com op = SkRegion::kReplace_Op; 136445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com } 136545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com 13660017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1369ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.orgbool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, 1370ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org bool inverseFilled) { 1371ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // This is for updating the clip conservatively using only bounds 1372ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // information. 1373ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Contract: 1374ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // The current clip must contain the true clip. The true 1375ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // clip is the clip that would have normally been computed 1376ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // by calls to clipPath and clipRRect 1377ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Objective: 1378ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Keep the current clip as small as possible without 1379ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // breaking the contract, using only clip bounding rectangles 1380ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // (for performance). 1381ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org 1382ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // N.B.: This *never* calls back through a virtual on canvas, so subclasses 1383ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // don't have to worry about getting caught in a loop. Thus anywhere 1384ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // we call a virtual method, we explicitly prefix it with 1385ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // SkCanvas:: to be sure to call the base-class. 1386a5d3e77420621c912383c3b22e542d9413d68278skia.committer@gmail.com 1387ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org if (inverseFilled) { 1388ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org switch (op) { 1389ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kIntersect_Op: 1390ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kDifference_Op: 1391ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // These ops can only shrink the current clip. So leaving 1392ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // the clip unchanges conservatively respects the contract. 1393ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->getClipDeviceBounds(NULL); 1394ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kUnion_Op: 1395ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReplace_Op: 1396ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReverseDifference_Op: 1397ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kXOR_Op: 1398ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org { 1399ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // These ops can grow the current clip up to the extents of 1400ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // the input clip, which is inverse filled, so we just set 1401ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // the current clip to the device bounds. 1402ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkRect deviceBounds; 1403ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkIRect deviceIBounds; 1404ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->getDevice()->getGlobalBounds(&deviceIBounds); 14054469938e92d779dff05e745559e67907bbf21e78reed@google.com deviceBounds = SkRect::Make(deviceIBounds); 1406ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); 1407ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // set the clip in device space 1408ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->SkCanvas::setMatrix(SkMatrix::I()); 1409ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org bool result = this->SkCanvas::clipRect(deviceBounds, 1410ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkRegion::kReplace_Op, false); 1411ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org this->SkCanvas::restore(); //pop the matrix, but keep the clip 1412ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return result; 1413ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1414ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org default: 1415ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkASSERT(0); // unhandled op? 1416ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1417ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } else { 1418ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Not inverse filled 1419ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org switch (op) { 1420ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kIntersect_Op: 1421ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kUnion_Op: 1422ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReplace_Op: 1423ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->SkCanvas::clipRect(bounds, op, false); 1424ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kDifference_Op: 1425ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Difference can only shrink the current clip. 1426ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Leaving clip unchanged conservatively fullfills the contract. 1427ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->getClipDeviceBounds(NULL); 1428ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kReverseDifference_Op: 1429ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // To reverse, we swap in the bounds with a replace op. 1430ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // As with difference, leave it unchanged. 1431ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false); 1432ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org case SkRegion::kXOR_Op: 1433ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // Be conservative, based on (A XOR B) always included in (A union B), 1434ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org // which is always included in (bounds(A) union bounds(B)) 1435ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false); 1436ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org default: 1437ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org SkASSERT(0); // unhandled op? 1438ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1439ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org } 1440ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org return true; 1441ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org} 1442ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 14445c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com AutoValidateClip avc(this); 14455c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDeviceCMDirty = true; 1447c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com fCachedLocalClipBoundsDirty = true; 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // todo: signal fClipStack that we have a region, and therefore (I guess) 14505c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com // we have to ignore it, and use the region directly? 1451115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com fClipStack.clipDevRect(rgn.getBounds(), op); 14525c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 14530017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->op(rgn, op); 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1456819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG 1457819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const { 1458819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // construct clipRgn from the clipstack 14591f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com const SkBaseDevice* device = this->getDevice(); 1460ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com if (!device) { 1461ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com SkASSERT(this->getTotalClip().isEmpty()); 1462ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com return; 1463ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com } 1464ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com 1465819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com SkIRect ir; 1466819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com ir.set(0, 0, device->width(), device->height()); 14670017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkRasterClip tmpClip(ir); 1468819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 146980214e26c57c5fea954006400852e8999e201923robertphillips@google.com SkClipStack::B2TIter iter(fClipStack); 14708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* element; 14718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com while ((element = iter.next()) != NULL) { 14728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 14738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kPath_Type: 14748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com clipPathHelper(this, 14758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com &tmpClip, 14768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getPath(), 14778182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getOp(), 14788182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->isAA()); 14798182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 14808182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kRect_Type: 14818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getRect().round(&ir); 14828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com tmpClip.op(ir, element->getOp()); 14838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 14848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kEmpty_Type: 14858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com tmpClip.setEmpty(); 14868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 1487819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1488819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com } 1489819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 14906f8f292aa768869a9e85c314b124875f57504f2creed@google.com#if 0 // enable this locally for testing 1491819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com // now compare against the current rgn 1492819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com const SkRegion& rgn = this->getTotalClip(); 14930017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com SkASSERT(rgn == tmpClip); 149402878b844c5cd3f17d48842da3ccf44a66621501reed@google.com#endif 1495819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com} 1496819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif 1497819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com 149890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const { 149980214e26c57c5fea954006400852e8999e201923robertphillips@google.com SkClipStack::B2TIter iter(fClipStack); 15008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com const SkClipStack::Element* element; 15018182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com 15028182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com static const SkRect kEmpty = { 0, 0, 0, 0 }; 15038182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com while ((element = iter.next()) != NULL) { 15048182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 15058182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kPath_Type: 15068182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com visitor->clipPath(element->getPath(), element->getOp(), element->isAA()); 15078182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 15088182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kRect_Type: 15098182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com visitor->clipRect(element->getRect(), element->getOp(), element->isAA()); 15108182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 15118182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case SkClipStack::Element::kEmpty_Type: 15128182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false); 15138182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 151490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } 151590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com } 151690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com} 151790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com 15185c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com/////////////////////////////////////////////////////////////////////////////// 15195c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com 15203b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const { 1521116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 15221607863b608b7db6c813228768ed5d72997bbc82reed@google.com if (!rect.isFinite()) 1523116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org return true; 1524116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org 15250017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) { 15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15298d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (fMCRec->fMatrix->hasPerspective()) { 1530a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkRect dst; 1531a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com fMCRec->fMatrix->mapRect(&dst, rect); 1532a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com SkIRect idst; 1533a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com dst.roundOut(&idst); 15340017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); 1535a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } else { 1536c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com const SkRect& clipR = this->getLocalClipBounds(); 1537d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 1538a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com // for speed, do the most likely reject compares first 1539c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com // TODO: should we use | instead, or compare all 4 at once? 1540c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1541a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1542a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1543c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1544a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return true; 1545a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com } 1546a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com return false; 15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15503b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const { 15513b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com return path.isEmpty() || this->quickReject(path.getBounds()); 15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15543b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const { 1555bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkIRect ibounds; 1556bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (!getClipDeviceBounds(&ibounds)) { 15578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1560d9c0f0b57affec7a472879c5919acac6637d926areed@android.com SkMatrix inverse; 1561d9c0f0b57affec7a472879c5919acac6637d926areed@android.com // if we can't invert the CTM, we can't return local clip bounds 1562d9c0f0b57affec7a472879c5919acac6637d926areed@android.com if (!fMCRec->fMatrix->invert(&inverse)) { 156372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com if (bounds) { 156472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com bounds->setEmpty(); 156572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com } 1566d9c0f0b57affec7a472879c5919acac6637d926areed@android.com return false; 1567d9c0f0b57affec7a472879c5919acac6637d926areed@android.com } 1568d9c0f0b57affec7a472879c5919acac6637d926areed@android.com 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != bounds) { 1570bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com SkRect r; 15713b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com // adjust it outwards in case we are antialiasing 15723b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com const int inset = 1; 1573fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com 15748f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 15758f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com ibounds.fRight + inset, ibounds.fBottom + inset); 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverse.mapRect(bounds, r); 15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1581bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 15820017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com const SkRasterClip& clip = *fMCRec->fRasterClip; 1583bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (clip.isEmpty()) { 1584bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (bounds) { 1585bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com bounds->setEmpty(); 1586bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1587bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return false; 1588bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1589bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 1590bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com if (NULL != bounds) { 1591bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com *bounds = clip.getBounds(); 1592bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com } 1593bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return true; 1594bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1595bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const { 15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *fMCRec->fMatrix; 15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1600bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const { 16010017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType; 16020017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com if (fMCRec->fRasterClip->isRect()) return kRect_ClipType; 1603bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com return kComplex_ClipType; 1604bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com} 1605bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com 16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const { 16070017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com return fMCRec->fRasterClip->forceGetBW(); 16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, 161150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org int width, int height, 161250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org bool isOpaque) { 16131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice* device = this->getTopDevice(); 1614cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com if (device) { 1615cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return device->createCompatibleDeviceForSaveLayer(config, width, height, 1616cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com isOpaque); 1617e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } else { 1618cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com return NULL; 1619e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com } 16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1622644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() { 1623644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU 1624644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org SkBaseDevice* device = this->getTopDevice(); 1625644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org if (NULL != device) { 1626644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org GrRenderTarget* renderTarget = device->accessRenderTarget(); 1627644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org if (NULL != renderTarget) { 1628644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org return renderTarget->getContext(); 1629644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org } 1630644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org } 1631644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif 1632644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org 1633644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org return NULL; 1634644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org 1635644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org} 1636e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com 16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These are the virtual drawing methods 16398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16412a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) { 16422a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com SkDrawIter iter(this); 1643995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org this->predrawNotify(); 16442a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com while (iter.next()) { 16452a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com iter.fDevice->clear(color); 16462a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com } 16472a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com} 16482a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com 16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) { 1650fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1651fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com} 1652fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com 1653fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) { 1654ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1655ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 165678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 16594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPaint(iter, looper.paint()); 16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 16668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1671ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1672ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 167378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect r, storage; 167478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL; 1675a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com if (paint.canComputeFastBounds()) { 1676a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com // special-case 2 points (common for drawing a single line) 1677a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com if (2 == count) { 1678a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com r.set(pts[0], pts[1]); 1679a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com } else { 1680a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org r.set(pts, SkToInt(count)); 1681a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com } 168278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bounds = &paint.computeFastStrokeBounds(r, &storage); 168378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org if (this->quickReject(*bounds)) { 1684a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com return; 1685a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com } 1686fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1687a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com 16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 169078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 16914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 16934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 16964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16997ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1700ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1701ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 170278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect storage; 170378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL; 17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 170578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bounds = &paint.computeFastBounds(r, &storage); 170678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org if (this->quickReject(*bounds)) { 17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17104b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 171178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 17144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawRect(iter, r, looper.paint()); 17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1721ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1722ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 172378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect storage; 172478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL; 17254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (paint.canComputeFastBounds()) { 172678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bounds = &paint.computeFastBounds(oval, &storage); 172778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org if (this->quickReject(*bounds)) { 17284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return; 17294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 17304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 1731306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com 173278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 173346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 173446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com while (iter.next()) { 173546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com iter.fDevice->drawOval(iter, oval, looper.paint()); 173646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com } 173746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 173846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com LOOPER_END 17394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 17404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 17414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1742ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1743ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 174478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect storage; 174578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL; 17464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (paint.canComputeFastBounds()) { 174778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 174878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org if (this->quickReject(*bounds)) { 17494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return; 17504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 17514ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 17524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 17534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com if (rrect.isRect()) { 17544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 17554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->SkCanvas::drawRect(rrect.getBounds(), paint); 1756f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org return; 1757f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } else if (rrect.isOval()) { 17584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // call the non-virtual version 1759f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org this->SkCanvas::drawOval(rrect.getBounds(), paint); 1760f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org return; 17614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com } 1762f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 176378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1764f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1765f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org while (iter.next()) { 1766f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1767f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } 1768f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1769f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org LOOPER_END 17704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 17714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 17724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 17737ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1774ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 1775ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 17769364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com if (!path.isFinite()) { 17779364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com return; 17789364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com } 17799364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com 178078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect storage; 178178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = NULL; 1782fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 178378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect& pathBounds = path.getBounds(); 178478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org bounds = &paint.computeFastBounds(pathBounds, &storage); 178578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org if (this->quickReject(*bounds)) { 17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1789fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isEmpty()) { 1790fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isInverseFillType()) { 1791fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->internalDrawPaint(paint); 1792fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 1793fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com return; 1794fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 179678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 17994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com iter.fDevice->drawPath(iter, path, looper.paint()); 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18093d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 18109efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com SkRect bounds = { 18119efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com x, y, 18129efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com x + SkIntToScalar(bitmap.width()), 18139efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com y + SkIntToScalar(bitmap.height()) 18149efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com }; 18159efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (paint) { 18169efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com (void)paint->computeFastBounds(bounds, &bounds); 18179efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com } 18183b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(bounds)) { 18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18224b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(x, y); 18259bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com this->internalDrawBitmap(bitmap, matrix, paint); 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18289987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis 18297112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 1830eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org const SkRect& dst, const SkPaint* paint, 1831eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org DrawBitmapRectFlags flags) { 183250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org if (bitmap.drawsNothing() || dst.isEmpty()) { 18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 183574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 1836ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_LOCKCOUNT_BALANCE(bitmap); 1837ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 183878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org SkRect storage; 183978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org const SkRect* bounds = &dst; 18403d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 18419efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com if (paint) { 18429efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com bounds = &paint->computeFastBounds(dst, &storage); 18439efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com } 18443b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(*bounds)) { 18453d60812865bb034851da777a91413ab584929887reed@google.com return; 18463d60812865bb034851da777a91413ab584929887reed@google.com } 18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18483d60812865bb034851da777a91413ab584929887reed@google.com 184933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com SkLazyPaint lazy; 185033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com if (NULL == paint) { 185133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com paint = lazy.init(); 18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18537064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com 185478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 18557064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com 185633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com while (iter.next()) { 1857eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 1858f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 18597064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com 186033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com LOOPER_END 18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18637112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 1864eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org const SkRect& dst, const SkPaint* paint, 1865eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org DrawBitmapRectFlags flags) { 18669987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 1867eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 18689987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 18699987ec3791336bad6af5cbe513564786b2df55aareed@google.com 18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint) { 18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(bitmap.validate();) 18739bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com this->internalDrawBitmap(bitmap, matrix, paint); 18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18769987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 18779987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkIRect& center, const SkRect& dst, 18789987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkPaint* paint) { 187950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org if (bitmap.drawsNothing()) { 188050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org return; 188150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org } 18823d60812865bb034851da777a91413ab584929887reed@google.com if (NULL == paint || paint->canComputeFastBounds()) { 188360abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com SkRect storage; 188460abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com const SkRect* bounds = &dst; 188560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com if (paint) { 188660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com bounds = &paint->computeFastBounds(dst, &storage); 188760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com } 18883b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(*bounds)) { 18893d60812865bb034851da777a91413ab584929887reed@google.com return; 18903d60812865bb034851da777a91413ab584929887reed@google.com } 18913d60812865bb034851da777a91413ab584929887reed@google.com } 18923d60812865bb034851da777a91413ab584929887reed@google.com 18939987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t w = bitmap.width(); 18949987ec3791336bad6af5cbe513564786b2df55aareed@google.com const int32_t h = bitmap.height(); 18959987ec3791336bad6af5cbe513564786b2df55aareed@google.com 18969987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkIRect c = center; 18979987ec3791336bad6af5cbe513564786b2df55aareed@google.com // pin center to the bounds of the bitmap 18989987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fLeft = SkMax32(0, center.fLeft); 18999987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fTop = SkMax32(0, center.fTop); 19009987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fRight = SkPin32(center.fRight, c.fLeft, w); 19019987ec3791336bad6af5cbe513564786b2df55aareed@google.com c.fBottom = SkPin32(center.fBottom, c.fTop, h); 19029987ec3791336bad6af5cbe513564786b2df55aareed@google.com 19037112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com const SkScalar srcX[4] = { 19047d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 19057112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com }; 19067112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com const SkScalar srcY[4] = { 19077d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 19087112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com }; 19099987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstX[4] = { 19109987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 19119987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 19129987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 19139987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkScalar dstY[4] = { 19149987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 19159987ec3791336bad6af5cbe513564786b2df55aareed@google.com dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 19169987ec3791336bad6af5cbe513564786b2df55aareed@google.com }; 191774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 19189987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstX[1] > dstX[2]) { 19199987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 19209987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstX[2] = dstX[1]; 19219987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 192274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 19239987ec3791336bad6af5cbe513564786b2df55aareed@google.com if (dstY[1] > dstY[2]) { 19249987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 19259987ec3791336bad6af5cbe513564786b2df55aareed@google.com dstY[2] = dstY[1]; 19269987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 192774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org 19289987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int y = 0; y < 3; y++) { 19297112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com SkRect s, d; 19307112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com 19319987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fTop = srcY[y]; 19329987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fBottom = srcY[y+1]; 19339987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fTop = dstY[y]; 19349987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fBottom = dstY[y+1]; 19359987ec3791336bad6af5cbe513564786b2df55aareed@google.com for (int x = 0; x < 3; x++) { 19369987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fLeft = srcX[x]; 19379987ec3791336bad6af5cbe513564786b2df55aareed@google.com s.fRight = srcX[x+1]; 19389987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fLeft = dstX[x]; 19399987ec3791336bad6af5cbe513564786b2df55aareed@google.com d.fRight = dstX[x+1]; 1940eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org this->internalDrawBitmapRect(bitmap, &s, d, paint, 194131acc11977815402e4ef2681350f8559285bec97robertphillips@google.com kNone_DrawBitmapRectFlag); 19429987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 19439987ec3791336bad6af5cbe513564786b2df55aareed@google.com } 19449987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 19459987ec3791336bad6af5cbe513564786b2df55aareed@google.com 19469987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 19479987ec3791336bad6af5cbe513564786b2df55aareed@google.com const SkRect& dst, const SkPaint* paint) { 19489987ec3791336bad6af5cbe513564786b2df55aareed@google.com SkDEBUGCODE(bitmap.validate();) 19499987ec3791336bad6af5cbe513564786b2df55aareed@google.com 19509987ec3791336bad6af5cbe513564786b2df55aareed@google.com // Need a device entry-point, so gpu can use a mesh 19519987ec3791336bad6af5cbe513564786b2df55aareed@google.com this->internalDrawBitmapNine(bitmap, center, dst, paint); 19529987ec3791336bad6af5cbe513564786b2df55aareed@google.com} 19539987ec3791336bad6af5cbe513564786b2df55aareed@google.com 1954f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint { 1955f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic: 19561f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 19571f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com SkBaseDevice::TextFlags flags; 1958f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com if (device->filterTextFlags(paint, &flags)) { 1959a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com SkPaint* newPaint = fLazy.set(paint); 1960f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setFlags(flags.fFlags); 1961f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com newPaint->setHinting(flags.fHinting); 1962f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = newPaint; 1963f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } else { 1964f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com fPaint = &paint; 1965f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1966f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com } 1967f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1968f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com const SkPaint& paint() const { return *fPaint; } 1969f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 1970f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate: 19712c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org const SkPaint* fPaint; 19722c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org SkLazyPaint fLazy; 1973f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com}; 1974f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com 197552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 197652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const SkRect& r, SkScalar textSize) { 197717b78946096265d80215a6c946286ecaa35ea7edepoger@google.com if (paint.getStyle() == SkPaint::kFill_Style) { 197852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, paint); 197952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else { 198052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint p(paint); 198117b78946096265d80215a6c946286ecaa35ea7edepoger@google.com p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 198252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fDevice->drawRect(draw, r, p); 198352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 198452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 198552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 198652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 198752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com const char text[], size_t byteLength, 198852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar x, SkScalar y) { 198952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkASSERT(byteLength == 0 || text != NULL); 199052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 199152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com // nothing to draw 199252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (text == NULL || byteLength == 0 || 199352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com draw.fClip->isEmpty() || 199452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 199552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 199652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 199752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 199852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar width = 0; 199952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPoint start; 200052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 200152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(0, 0); // to avoid warning 200252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 200352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 200452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com width = paint.measureText(text, byteLength); 200552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 200652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offsetX = 0; 200752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 200852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = SkScalarHalf(width); 200952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 201052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com offsetX = width; 201152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 201252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.set(x - offsetX, y); 201352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 201452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 201552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (0 == width) { 201652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com return; 201752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 201852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 201952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com uint32_t flags = paint.getFlags(); 202052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 202152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & (SkPaint::kUnderlineText_Flag | 202252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkPaint::kStrikeThruText_Flag)) { 202352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar textSize = paint.getTextSize(); 202452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 202552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkRect r; 202652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 202752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fLeft = start.fX; 202852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fRight = start.fX + width; 202952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 203052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kUnderlineText_Flag) { 203152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 203252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 203352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 203452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 203552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 203652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 203752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com if (flags & SkPaint::kStrikeThruText_Flag) { 203852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 203952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com start.fY); 204052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fTop = offset; 204152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com r.fBottom = offset + height; 204252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawRect(draw, paint, r, textSize); 204352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 204452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com } 204552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com} 204652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com 20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength, 20488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) { 2049ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2050ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 205178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 20544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2055f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 205652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com DrawTextDecorations(iter, dfp.paint(), 205752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com static_cast<const char*>(text), byteLength, x, y); 20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, 20648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pos[], const SkPaint& paint) { 2065ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2066ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 206778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 20684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 20704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 2072f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, 20798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar xpos[], SkScalar constY, 20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 2081ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2082ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 208378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 20844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 20864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 20878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 2088f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com dfp.paint()); 20898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 20914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 20928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, const SkMatrix* matrix, 20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 2097ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2098ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 209978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 21028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 21034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com matrix, looper.paint()); 21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint verts[], const SkPoint texs[], 21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 2114ea033606a06d05d2d42aa7118409fee798e53167reed@google.com CHECK_SHADER_NOSETCONTEXT(paint); 2115ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 211678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 21174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next()) { 21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 21204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com colors, xmode, indices, indexCount, 21214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com looper.paint()); 21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com LOOPER_END 21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 21288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual 21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves. 21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2133845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode) { 21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setARGB(a, r, g, b); 2137845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 21380baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 21418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2143845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 21448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 21458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(c); 2147845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode != mode) { 21480baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com paint.setXfermodeMode(mode); 21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPaint(paint); 21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 21554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 21578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 21628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 21634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(x, y); 21658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setColor(color); 21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kPoints_PointMode, 1, &pt, paint); 21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[2]; 21724b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[0].set(x0, y0); 21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts[1].set(x1, y1); 21758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPoints(kLines_PointMode, 2, pts, paint); 21768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 21798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar right, SkScalar bottom, 21808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, top, right, bottom); 21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 21898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (radius < 0) { 21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com radius = 0; 21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(cx - radius, cy - radius, cx + radius, cy + radius); 21954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->drawOval(r, paint); 21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 21998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx > 0 && ry > 0) { 22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.canComputeFastBounds()) { 22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect storage; 22033b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com if (this->quickReject(paint.computeFastBounds(r, &storage))) { 22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkRRect rrect; 22084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com rrect.setRectXY(r, rx, ry); 22094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->drawRRect(rrect, paint); 22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sweepAngle, bool useCenter, 22178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 22188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 22198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawOval(oval, paint); 22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 22228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(oval.centerX(), oval.centerY()); 22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.arcTo(oval, startAngle, sweepAngle, !useCenter); 22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (useCenter) { 22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.close(); 22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint); 22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& path, SkScalar hOffset, 22358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar vOffset, const SkPaint& paint) { 22368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 22374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com 22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(hOffset, vOffset); 22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawTextOnPath(text, byteLength, path, &matrix, paint); 22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2242f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com/////////////////////////////////////////////////////////////////////////////// 2243f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com 22448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) { 22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com picture.draw(this); 22468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2252d642329293cce602ac24df8f585c14a98795da87reed@google.com SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(canvas); 22558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 22578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 22588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() { 22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fImpl->~SkDrawIter(); 22628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() { 22658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = !fImpl->next(); 22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const { 22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getDevice(); 22708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const { 22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fImpl->getMatrix(); 22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const { 22778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* paint = fImpl->getPaint(); 22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint) { 22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint = &fDefaultPaint; 22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *paint; 22828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 22858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); } 22868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); } 228720a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com 228820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com/////////////////////////////////////////////////////////////////////////////// 228920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com 229020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.comSkCanvas::ClipVisitor::~ClipVisitor() { } 2291