153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com/* 253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * Copyright 2013 Google Inc. 353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * 453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * found in the LICENSE file. 653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com */ 753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 8986480a71f4e860663ced7ad90a1fe346a164afbMike Reed#include "SkBitmapDevice.h" 953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkDraw.h" 10e51c356ae4e074b9c286c50a4efce11205f7463creed#include "SkImageFilter.h" 11900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilterCache.h" 12cd4954152490c7492284a7914571531ba8c75b4amtklein#include "SkMallocPixelRef.h" 13d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkMatrix.h" 14d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkPaint.h" 15d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkPath.h" 16884e97cb04db7ed053a866567ee9c6e4c01f993areed#include "SkPixelRef.h" 17d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkPixmap.h" 18e51c356ae4e074b9c286c50a4efce11205f7463creed#include "SkRasterClip.h" 19356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#include "SkRasterHandleAllocator.h" 2053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkShader.h" 21e51c356ae4e074b9c286c50a4efce11205f7463creed#include "SkSpecialImage.h" 2276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com#include "SkSurface.h" 2353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita#include "SkTLazy.h" 242f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed#include "SkVertices.h" 25d3ebb48320cf1b7e969974673e4bd7743816985ebungeman 26d3ebb48320cf1b7e969974673e4bd7743816985ebungemanclass SkColorTable; 2753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 2815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgstatic bool valid_for_bitmap_device(const SkImageInfo& info, 2915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkAlphaType* newAlphaType) { 3015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (info.width() < 0 || info.height() < 0) { 3115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return false; 3215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 3315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 3415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org // TODO: can we stop supporting kUnknown in SkBitmkapDevice? 3515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (kUnknown_SkColorType == info.colorType()) { 3615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (newAlphaType) { 3744977485bdac75c055c3fa638f118874ccd2d22freed *newAlphaType = kUnknown_SkAlphaType; 3815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 3915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return true; 4015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 41969588f0c9030d5a4942085a4b5a5ea7e8d2bc25skia.committer@gmail.com 4215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkAlphaType canonicalAlphaType = info.alphaType(); 4315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 4415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org switch (info.colorType()) { 4515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org case kAlpha_8_SkColorType: 46ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kARGB_4444_SkColorType: 47ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kRGBA_8888_SkColorType: 48ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kBGRA_8888_SkColorType: 49ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kRGBA_1010102_SkColorType: 50ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kRGBA_F16_SkColorType: 5115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org break; 52515bda681177e2bb1c988e3167a95e3d4132bd7fMike Klein case kGray_8_SkColorType: 5315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org case kRGB_565_SkColorType: 54ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kRGB_888x_SkColorType: 55ac568a934f8f82bf3a359b757d67eb3a797d3593Mike Klein case kRGB_101010x_SkColorType: 5615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org canonicalAlphaType = kOpaque_SkAlphaType; 5715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org break; 5815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org default: 5915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return false; 6015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 6115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 6215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (newAlphaType) { 6315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org *newAlphaType = canonicalAlphaType; 6415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 6515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return true; 6615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org} 6715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 689a53fd7c41554630124522f4b6eedc16912abbb7robertphillipsSkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) 69589a39eb81d25fa7af95e7366db17ac7a70a7d03reed : INHERITED(bitmap.info(), SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)) 702c9e20055be772feb3f44986c1af0c0a979eff49reed , fBitmap(bitmap) 71c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed , fRCStack(bitmap.width(), bitmap.height()) 722c9e20055be772feb3f44986c1af0c0a979eff49reed{ 7396fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr)); 7453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 7553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 769a53fd7c41554630124522f4b6eedc16912abbb7robertphillipsSkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& info) { 779a53fd7c41554630124522f4b6eedc16912abbb7robertphillips return Create(info, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)); 789a53fd7c41554630124522f4b6eedc16912abbb7robertphillips} 799a53fd7c41554630124522f4b6eedc16912abbb7robertphillips 80356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& surfaceProps, 81356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed SkRasterHandleAllocator::Handle hndl) 82589a39eb81d25fa7af95e7366db17ac7a70a7d03reed : INHERITED(bitmap.info(), surfaceProps) 832c9e20055be772feb3f44986c1af0c0a979eff49reed , fBitmap(bitmap) 84356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed , fRasterHandle(hndl) 85c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed , fRCStack(bitmap.width(), bitmap.height()) 862c9e20055be772feb3f44986c1af0c0a979eff49reed{ 8796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr)); 8853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 8953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 9015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo, 91356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed const SkSurfaceProps& surfaceProps, 92356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed SkRasterHandleAllocator* allocator) { 93e5ea500d4714a7d84de2bf913e81be3b65d2de68reed SkAlphaType newAT = origInfo.alphaType(); 94e5ea500d4714a7d84de2bf913e81be3b65d2de68reed if (!valid_for_bitmap_device(origInfo, &newAT)) { 9596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 9615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 9715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 98356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed SkRasterHandleAllocator::Handle hndl = nullptr; 99e5ea500d4714a7d84de2bf913e81be3b65d2de68reed const SkImageInfo info = origInfo.makeAlphaType(newAT); 10015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkBitmap bitmap; 10115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 10215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (kUnknown_SkColorType == info.colorType()) { 103a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org if (!bitmap.setInfo(info)) { 10496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 10515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 106356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed } else if (allocator) { 107356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed hndl = allocator->allocBitmap(info, &bitmap); 108356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed if (!hndl) { 109356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed return nullptr; 110356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed } 11104d975ac34c97d4869f819d2ad7c9fda47c198aflsalzman } else if (info.isOpaque()) { 112cd4954152490c7492284a7914571531ba8c75b4amtklein // If this bitmap is opaque, we don't have any sensible default color, 113cd4954152490c7492284a7914571531ba8c75b4amtklein // so we just return uninitialized pixels. 114848250415eddc54075f7eb8795e8db79e749c6abreed if (!bitmap.tryAllocPixels(info)) { 11596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 11615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 117cd4954152490c7492284a7914571531ba8c75b4amtklein } else { 118cd4954152490c7492284a7914571531ba8c75b4amtklein // This bitmap has transparency, so we'll zero the pixels (to transparent). 1196b3155c4be0476bc53541b0431c368a44e69f0a7Mike Reed // We use the flag as a faster alloc-then-eraseColor(SK_ColorTRANSPARENT). 120086a427b0cee3862f25c492fc5082ff24105dc53Mike Reed if (!bitmap.tryAllocPixelsFlags(info, SkBitmap::kZeroPixels_AllocFlag)) { 121cd4954152490c7492284a7914571531ba8c75b4amtklein return nullptr; 12215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 12315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 12453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 125356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed return new SkBitmapDevice(bitmap, surfaceProps, hndl); 12653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 12753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 12853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) { 12953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkASSERT(bm.width() == fBitmap.width()); 13053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkASSERT(bm.height() == fBitmap.height()); 13153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config) 132589a39eb81d25fa7af95e7366db17ac7a70a7d03reed this->privateResize(fBitmap.info().width(), fBitmap.info().height()); 13353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 13453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 13576033be81b82c44fd5d4fdf2672eb22e505da1f0reedSkBaseDevice* SkBitmapDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) { 1369a53fd7c41554630124522f4b6eedc16912abbb7robertphillips const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry); 137356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed return SkBitmapDevice::Create(cinfo.fInfo, surfaceProps, cinfo.fAllocator); 13853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 13953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 140884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkBitmapDevice::onAccessPixels(SkPixmap* pmap) { 141b560b5c8c03fe1b9b1b8a90c546481b8db7f043ereed if (this->onPeekPixels(pmap)) { 1426e764859dabf265fae03066376e7446a87e0ad09reed fBitmap.notifyPixelsChanged(); 1436e764859dabf265fae03066376e7446a87e0ad09reed return true; 1446e764859dabf265fae03066376e7446a87e0ad09reed } 1456e764859dabf265fae03066376e7446a87e0ad09reed return false; 1469572a10c9a6a868bbb8f71d7806d0a45f183333freed} 1479572a10c9a6a868bbb8f71d7806d0a45f183333freed 1489572a10c9a6a868bbb8f71d7806d0a45f183333freedbool SkBitmapDevice::onPeekPixels(SkPixmap* pmap) { 149884e97cb04db7ed053a866567ee9c6e4c01f993areed const SkImageInfo info = fBitmap.info(); 150884e97cb04db7ed053a866567ee9c6e4c01f993areed if (fBitmap.getPixels() && (kUnknown_SkColorType != info.colorType())) { 151086a427b0cee3862f25c492fc5082ff24105dc53Mike Reed pmap->reset(fBitmap.info(), fBitmap.getPixels(), fBitmap.rowBytes()); 152884e97cb04db7ed053a866567ee9c6e4c01f993areed return true; 1539c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com } 154884e97cb04db7ed053a866567ee9c6e4c01f993areed return false; 1559c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com} 1569c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com 157353196f44f8c4f5fc3dc3783241faef264b80927Mike Reedbool SkBitmapDevice::onWritePixels(const SkPixmap& pm, int x, int y) { 1580d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com // since we don't stop creating un-pixeled devices yet, check for no pixels here 15996fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fBitmap.getPixels()) { 1600d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com return false; 1610d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com } 1620d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com 163353196f44f8c4f5fc3dc3783241faef264b80927Mike Reed if (fBitmap.writePixels(pm, x, y)) { 1644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org fBitmap.notifyPixelsChanged(); 1654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org return true; 1664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org } 1674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org return false; 1684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} 16953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 170353196f44f8c4f5fc3dc3783241faef264b80927Mike Reedbool SkBitmapDevice::onReadPixels(const SkPixmap& pm, int x, int y) { 171353196f44f8c4f5fc3dc3783241faef264b80927Mike Reed return fBitmap.readPixels(pm, x, y); 172a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org} 173a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org 17453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 17553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 176a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedclass SkBitmapDevice::BDDraw : public SkDraw { 177c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedpublic: 178a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(SkBitmapDevice* dev) { 179a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // we need fDst to be set, and if we're actually drawing, to dirty the genID 180a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed if (!dev->accessPixels(&fDst)) { 181a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels 182a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed fDst.reset(dev->imageInfo(), nullptr, 0); 183a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed } 184a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed fMatrix = &dev->ctm(); 185a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed fRC = &dev->fRCStack.rc(); 186c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 187c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed}; 188c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 189a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawPaint(const SkPaint& paint) { 190a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawPaint(paint); 19153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 19253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 193a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawPoints(SkCanvas::PointMode mode, size_t count, 19453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPoint pts[], const SkPaint& paint) { 195a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawPoints(mode, count, pts, paint, nullptr); 19653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 19753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 198a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawRect(const SkRect& r, const SkPaint& paint) { 199a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawRect(r, paint); 20053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 20153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 202a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawOval(const SkRect& oval, const SkPaint& paint) { 20353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkPath path; 20453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com path.addOval(oval); 20553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // call the VIRTUAL version, so any subclasses who do handle drawPath aren't 20653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // required to override drawOval. 207a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed this->drawPath(path, paint, nullptr, true); 20853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 20953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 210a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 21150a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com#ifdef SK_IGNORE_BLURRED_RRECT_OPT 21250a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com SkPath path; 21350a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com 21450a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com path.addRRect(rrect); 21550a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com // call the VIRTUAL version, so any subclasses who do handle drawPath aren't 21650a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com // required to override drawRRect. 217a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed this->drawPath(path, paint, nullptr, true); 21850a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com#else 219a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawRRect(rrect, paint); 22050a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com#endif 22153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 22253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 223a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawPath(const SkPath& path, 22453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPaint& paint, const SkMatrix* prePathMatrix, 22553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com bool pathIsMutable) { 226a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawPath(path, paint, prePathMatrix, pathIsMutable); 22753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 22853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 229b964238f0bded00bae59c26c5f366a7780a0ef5fHal Canaryvoid SkBitmapDevice::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 230b964238f0bded00bae59c26c5f366a7780a0ef5fHal Canary const SkPaint& paint) { 231b964238f0bded00bae59c26c5f366a7780a0ef5fHal Canary SkMatrix matrix = SkMatrix::MakeTrans(x, y); 232a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed LogDrawScaleFactor(SkMatrix::Concat(this->ctm(), matrix), paint.getFilterQuality()); 233a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawBitmap(bitmap, matrix, nullptr, paint); 23453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 23553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 236ab83da71426195dad58a85e2caff213358c8461dfmalitastatic inline bool CanApplyDstMatrixAsCTM(const SkMatrix& m, const SkPaint& paint) { 237ab83da71426195dad58a85e2caff213358c8461dfmalita if (!paint.getMaskFilter()) { 238ab83da71426195dad58a85e2caff213358c8461dfmalita return true; 239ab83da71426195dad58a85e2caff213358c8461dfmalita } 240ab83da71426195dad58a85e2caff213358c8461dfmalita 241ab83da71426195dad58a85e2caff213358c8461dfmalita // Some mask filters parameters (sigma) depend on the CTM/scale. 242ab83da71426195dad58a85e2caff213358c8461dfmalita return m.getType() <= SkMatrix::kTranslate_Mask; 243ab83da71426195dad58a85e2caff213358c8461dfmalita} 244ab83da71426195dad58a85e2caff213358c8461dfmalita 245a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawBitmapRect(const SkBitmap& bitmap, 24653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkRect* src, const SkRect& dst, 247562fe4767cc73e08a4e039362bc0336aea66ecfbreed const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) { 24853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkMatrix matrix; 24953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkRect bitmapBounds, tmpSrc, tmpDst; 25053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkBitmap tmpBitmap; 25153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 25253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com bitmapBounds.isetWH(bitmap.width(), bitmap.height()); 25353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 25453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // Compute matrix from the two rectangles 25553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (src) { 25653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com tmpSrc = *src; 25753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } else { 25853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com tmpSrc = bitmapBounds; 25953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 26053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 26153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 262a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed LogDrawScaleFactor(SkMatrix::Concat(this->ctm(), matrix), paint.getFilterQuality()); 263983294f78f11159a7def7fd2ea0c12f911d17688ericrk 26453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkRect* dstPtr = &dst; 26553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkBitmap* bitmapPtr = &bitmap; 26653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 26753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if 26853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // needed (if the src was clipped). No check needed if src==null. 26953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (src) { 27053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (!bitmapBounds.contains(*src)) { 27153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (!tmpSrc.intersect(bitmapBounds)) { 27253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return; // nothing to draw 27353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 27453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // recompute dst, based on the smaller tmpSrc 27553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com matrix.mapRect(&tmpDst, tmpSrc); 27653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com dstPtr = &tmpDst; 27753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 27827efa2371e27d5306f214e4b0bda60848fd49c02reed } 27927efa2371e27d5306f214e4b0bda60848fd49c02reed 28027efa2371e27d5306f214e4b0bda60848fd49c02reed if (src && !src->contains(bitmapBounds) && 28127efa2371e27d5306f214e4b0bda60848fd49c02reed SkCanvas::kFast_SrcRectConstraint == constraint && 28227efa2371e27d5306f214e4b0bda60848fd49c02reed paint.getFilterQuality() != kNone_SkFilterQuality) { 28327efa2371e27d5306f214e4b0bda60848fd49c02reed // src is smaller than the bounds of the bitmap, and we are filtering, so we don't know 28427efa2371e27d5306f214e4b0bda60848fd49c02reed // how much more of the bitmap we need, so we can't use extractSubset or drawBitmap, 28527efa2371e27d5306f214e4b0bda60848fd49c02reed // but we must use a shader w/ dst bounds (which can access all of the bitmap needed). 28627efa2371e27d5306f214e4b0bda60848fd49c02reed goto USE_SHADER; 28727efa2371e27d5306f214e4b0bda60848fd49c02reed } 28853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 28927efa2371e27d5306f214e4b0bda60848fd49c02reed if (src) { 29053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // since we may need to clamp to the borders of the src rect within 29153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // the bitmap, we extract a subset. 292b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkIRect srcIR = tmpSrc.roundOut(); 29319fe41e85e6ce3e78b3a69fce1cf28edf937027dbsalomon if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { 29419fe41e85e6ce3e78b3a69fce1cf28edf937027dbsalomon return; 29553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 29653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com bitmapPtr = &tmpBitmap; 29753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 29853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // Since we did an extract, we need to adjust the matrix accordingly 29953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkScalar dx = 0, dy = 0; 30053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (srcIR.fLeft > 0) { 30153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com dx = SkIntToScalar(srcIR.fLeft); 30253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 30353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (srcIR.fTop > 0) { 30453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com dy = SkIntToScalar(srcIR.fTop); 30553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 30653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (dx || dy) { 30753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com matrix.preTranslate(dx, dy); 30853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 30953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 310c0e52f44aac391da632d88d9702aea4f41cfe17alsalzman#ifdef SK_DRAWBITMAPRECT_FAST_OFFSET 311c0e52f44aac391da632d88d9702aea4f41cfe17alsalzman SkRect extractedBitmapBounds = SkRect::MakeXYWH(dx, dy, 312c0e52f44aac391da632d88d9702aea4f41cfe17alsalzman SkIntToScalar(bitmapPtr->width()), 313c0e52f44aac391da632d88d9702aea4f41cfe17alsalzman SkIntToScalar(bitmapPtr->height())); 314c0e52f44aac391da632d88d9702aea4f41cfe17alsalzman#else 31565c74f1368290551c60e4cd46e08ea1d6970b3d3mtklein SkRect extractedBitmapBounds; 31665c74f1368290551c60e4cd46e08ea1d6970b3d3mtklein extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height()); 317c0e52f44aac391da632d88d9702aea4f41cfe17alsalzman#endif 31853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (extractedBitmapBounds == tmpSrc) { 31953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // no fractional part in src, we can just call drawBitmap 32053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com goto USE_DRAWBITMAP; 32153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 32253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } else { 32353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com USE_DRAWBITMAP: 32453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // We can go faster by just calling drawBitmap, which will concat the 32553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // matrix with the CTM, and try to call drawSprite if it can. If not, 32653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // it will make a shader and call drawRect, as we do below. 327ab83da71426195dad58a85e2caff213358c8461dfmalita if (CanApplyDstMatrixAsCTM(matrix, paint)) { 328a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawBitmap(*bitmapPtr, matrix, dstPtr, paint); 329ab83da71426195dad58a85e2caff213358c8461dfmalita return; 330ab83da71426195dad58a85e2caff213358c8461dfmalita } 33153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 33253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 33327efa2371e27d5306f214e4b0bda60848fd49c02reed USE_SHADER: 334f77c47b78217883e6f074dd7e3e5bed5f82e144dreed 33583e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby // TODO(herb): Move this over to SkArenaAlloc when arena alloc has a facility to return sk_sps. 336f77c47b78217883e6f074dd7e3e5bed5f82e144dreed // Since the shader need only live for our stack-frame, pass in a custom allocator. This 337f77c47b78217883e6f074dd7e3e5bed5f82e144dreed // can save malloc calls, and signals to SkMakeBitmapShader to not try to copy the bitmap 338f77c47b78217883e6f074dd7e3e5bed5f82e144dreed // if its mutable, since that precaution is not needed (give the short lifetime of the shader). 339bfdc87a62193aae20fac0bce37bed7b656f299bbHerb Derby 34053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // construct a shader, so we can call drawRect with the dst 341f77c47b78217883e6f074dd7e3e5bed5f82e144dreed auto s = SkMakeBitmapShader(*bitmapPtr, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, 342bfdc87a62193aae20fac0bce37bed7b656f299bbHerb Derby &matrix, kNever_SkCopyPixelsMode); 3438a21c9fe7f5fef9e87115defef27bd7218419f28reed if (!s) { 34453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return; 34553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 34653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 34753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkPaint paintWithShader(paint); 34853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paintWithShader.setStyle(SkPaint::kFill_Style); 349f77c47b78217883e6f074dd7e3e5bed5f82e144dreed paintWithShader.setShader(s); 35053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 35153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // Call ourself, in case the subclass wanted to share this setup code 35253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // but handle the drawRect code themselves. 353a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed this->drawRect(*dstPtr, paintWithShader); 35453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 35553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 3562f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reedvoid SkBitmapDevice::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& paint) { 357a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawSprite(bitmap, x, y, paint); 35853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 35953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 360a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawText(const void* text, size_t len, 36153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkScalar x, SkScalar y, const SkPaint& paint) { 362a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed BDDraw(this).drawText((const char*)text, len, x, y, paint, &fSurfaceProps); 36353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 36453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 365a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[], 366a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) { 3672f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed BDDraw(this).drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint, 3682f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed &fSurfaceProps); 36953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 37053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 3712f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reedvoid SkBitmapDevice::drawVertices(const SkVertices* vertices, SkBlendMode bmode, 37253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPaint& paint) { 3732f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed BDDraw(this).drawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(), 3742f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed vertices->texCoords(), vertices->colors(), bmode, 3752f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed vertices->indices(), vertices->indexCount(), paint); 37653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 37753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 378be33bab92b83c116cf3f62cff982a2ee7892717eMike Reedvoid SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPaint& origPaint) { 379be33bab92b83c116cf3f62cff982a2ee7892717eMike Reed SkASSERT(!origPaint.getImageFilter()); 380be33bab92b83c116cf3f62cff982a2ee7892717eMike Reed 381be33bab92b83c116cf3f62cff982a2ee7892717eMike Reed // todo: can we unify with similar adjustment in SkGpuDevice? 3822179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 3832179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed if (paint->getMaskFilter()) { 3842179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm())); 385be33bab92b83c116cf3f62cff982a2ee7892717eMike Reed } 386be33bab92b83c116cf3f62cff982a2ee7892717eMike Reed 387be33bab92b83c116cf3f62cff982a2ee7892717eMike Reed BDDraw(this).drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, *paint); 38853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 38953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 390e51c356ae4e074b9c286c50a4efce11205f7463creed/////////////////////////////////////////////////////////////////////////////// 391e51c356ae4e074b9c286c50a4efce11205f7463creed 39287f807136c216f5db12568afc2e5c8e893b99ef1Florin Malitanamespace { 39387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 39487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malitaclass SkAutoDeviceClipRestore { 39587f807136c216f5db12568afc2e5c8e893b99ef1Florin Malitapublic: 39687f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkAutoDeviceClipRestore(SkBaseDevice* device, const SkIRect& clip) 39787f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita : fDevice(device) 39887f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita , fPrevCTM(device->ctm()) { 39987f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita fDevice->save(); 40087f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita fDevice->setCTM(SkMatrix::I()); 40187f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita fDevice->clipRect(SkRect::Make(clip), SkClipOp::kIntersect, false); 40287f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita fDevice->setCTM(fPrevCTM); 40387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita } 40487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 40587f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita ~SkAutoDeviceClipRestore() { 40687f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita fDevice->restore(fPrevCTM); 40787f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita } 40887f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 40987f807136c216f5db12568afc2e5c8e893b99ef1Florin Malitaprivate: 41087f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkBaseDevice* fDevice; 41187f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita const SkMatrix fPrevCTM; 41287f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita}; 41387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 41487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita} // anonymous ns 41587f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 41653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malitavoid SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint, 41753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkImage* clipImage, const SkMatrix& clipMatrix) { 41853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkASSERT(!src->isTextureBacked()); 419e51c356ae4e074b9c286c50a4efce11205f7463creed 42053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita sk_sp<SkSpecialImage> filteredImage; 42153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 422e51c356ae4e074b9c286c50a4efce11205f7463creed 42353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita if (SkImageFilter* filter = paint->getImageFilter()) { 424e51c356ae4e074b9c286c50a4efce11205f7463creed SkIPoint offset = SkIPoint::Make(0, 0); 42553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita const SkMatrix matrix = SkMatrix::Concat( 42653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkMatrix::MakeTrans(SkIntToScalar(-x), SkIntToScalar(-y)), this->ctm()); 427a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed const SkIRect clipBounds = fRCStack.rc().getBounds().makeOffset(-x, -y); 428704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary sk_sp<SkImageFilterCache> cache(this->getImageFilterCache()); 4292a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman SkImageFilter::OutputProperties outputProperties(fBitmap.colorSpace()); 4302a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties); 4312add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian 43253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita filteredImage = filter->filterImage(src, ctx, &offset); 43353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita if (!filteredImage) { 43453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita return; 435e51c356ae4e074b9c286c50a4efce11205f7463creed } 43653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 43753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita src = filteredImage.get(); 43853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita paint.writable()->setImageFilter(nullptr); 43953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita x += offset.x(); 44053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita y += offset.y(); 44153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita } 44253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 4432179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed if (paint->getMaskFilter()) { 4442179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm())); 4452179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed } 4462179b78ef221b6df73f1b8a085e5ca86e85a525bMike Reed 44753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita if (!clipImage) { 44853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkBitmap resultBM; 44953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita if (src->getROPixels(&resultBM)) { 45053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita this->drawSprite(resultBM, x, y, *paint); 451e51c356ae4e074b9c286c50a4efce11205f7463creed } 45253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita return; 45353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita } 45453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 45553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita // Clip image case. 45653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita sk_sp<SkImage> srcImage(src->asImage()); 45753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita if (!srcImage) { 45853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita return; 459e51c356ae4e074b9c286c50a4efce11205f7463creed } 46053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 46153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita const SkMatrix totalMatrix = SkMatrix::Concat(this->ctm(), clipMatrix); 46253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkRect clipBounds; 46353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita totalMatrix.mapRect(&clipBounds, SkRect::Make(clipImage->bounds())); 46453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita const SkIRect srcBounds = srcImage->bounds().makeOffset(x, y); 46553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 46653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita SkIRect maskBounds = fRCStack.rc().getBounds(); 46753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita if (!maskBounds.intersect(clipBounds.roundOut()) || !maskBounds.intersect(srcBounds)) { 46853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita return; 46953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita } 47053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 47187f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita sk_sp<SkImage> mask; 47287f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkMatrix maskMatrix, shaderMatrix; 47387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkTLazy<SkAutoDeviceClipRestore> autoClipRestore; 47487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 47587f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkMatrix totalInverse; 47687f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita if (clipImage->isAlphaOnly() && totalMatrix.invert(&totalInverse)) { 47787f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita // If the mask is already in A8 format, we can draw it directly 47887f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita // (while compensating in the shader matrix). 47987f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita mask = sk_ref_sp(clipImage); 48087f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita maskMatrix = totalMatrix; 48187f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita shaderMatrix = SkMatrix::Concat(totalInverse, SkMatrix::MakeTrans(x, y)); 48287f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 48387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita // If the mask is not fully contained within the src layer, we must clip. 48487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita if (!srcBounds.contains(clipBounds)) { 48587f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita autoClipRestore.init(this, srcBounds); 48687f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita } 48753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 48887f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita maskBounds.offsetTo(0, 0); 48987f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita } else { 49087f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita // Otherwise, we convert the mask to A8 explicitly. 49187f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(), 49287f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita maskBounds.height())); 49387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkCanvas* canvas = surf->getCanvas(); 49487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita canvas->translate(-maskBounds.x(), -maskBounds.y()); 49587f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita canvas->concat(totalMatrix); 49687f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita canvas->drawImage(clipImage, 0, 0); 49787f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita 49887f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita mask = surf->makeImageSnapshot(); 49987f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita maskMatrix = SkMatrix::I(); 50087f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita shaderMatrix = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y()); 50187f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita } 50253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita 50387f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita SkAutoDeviceCTMRestore adctmr(this, maskMatrix); 50487f807136c216f5db12568afc2e5c8e893b99ef1Florin Malita paint.writable()->setShader(srcImage->makeShader(&shaderMatrix)); 50553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita this->drawImage(mask.get(), maskBounds.x(), maskBounds.y(), *paint); 506e51c356ae4e074b9c286c50a4efce11205f7463creed} 507e51c356ae4e074b9c286c50a4efce11205f7463creed 508e51c356ae4e074b9c286c50a4efce11205f7463creedsk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) { 509e51c356ae4e074b9c286c50a4efce11205f7463creed return SkSpecialImage::MakeFromRaster(bitmap.bounds(), bitmap); 510e51c356ae4e074b9c286c50a4efce11205f7463creed} 511e51c356ae4e074b9c286c50a4efce11205f7463creed 512e51c356ae4e074b9c286c50a4efce11205f7463creedsk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkImage* image) { 513e51c356ae4e074b9c286c50a4efce11205f7463creed return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image->height()), 51461624f0c716b576706659750d87b6956f4c15722Brian Osman image->makeNonTextureImage(), fBitmap.colorSpace()); 515e51c356ae4e074b9c286c50a4efce11205f7463creed} 516e51c356ae4e074b9c286c50a4efce11205f7463creed 517e51c356ae4e074b9c286c50a4efce11205f7463creedsk_sp<SkSpecialImage> SkBitmapDevice::snapSpecial() { 518e51c356ae4e074b9c286c50a4efce11205f7463creed return this->makeSpecial(fBitmap); 519e51c356ae4e074b9c286c50a4efce11205f7463creed} 520e51c356ae4e074b9c286c50a4efce11205f7463creed 521e51c356ae4e074b9c286c50a4efce11205f7463creed/////////////////////////////////////////////////////////////////////////////// 522e51c356ae4e074b9c286c50a4efce11205f7463creed 523e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkBitmapDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 524e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRaster(info, &props); 52576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com} 52676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com 527900c36779610dc65c42a5004ee3693fd70961ba4senorblancoSkImageFilterCache* SkBitmapDevice::getImageFilterCache() { 528900c36779610dc65c42a5004ee3693fd70961ba4senorblanco SkImageFilterCache* cache = SkImageFilterCache::Get(); 52955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco cache->ref(); 53055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco return cache; 53155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco} 53255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco 5337627fa51044e35dc21251f925b56f6dd6887df97Mike Reed/////////////////////////////////////////////////////////////////////////////////////////////////// 53453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 535b2db898573e3cdcc8234eebf51961bfc4977ebbcreedbool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const { 536cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org if (kN32_SkColorType != fBitmap.colorType() || 53753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.getPathEffect() || 53853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.isFakeBoldText() || 53953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.getStyle() != SkPaint::kFill_Style || 540374772bd61951f01bf84fe17bf53d8867681c9aereed !paint.isSrcOver()) 541b2db898573e3cdcc8234eebf51961bfc4977ebbcreed { 54253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return true; 54353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 54453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return false; 54553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 5467627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5477627fa51044e35dc21251f925b56f6dd6887df97Mike Reed/////////////////////////////////////////////////////////////////////////////////////////////////// 5487627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5497627fa51044e35dc21251f925b56f6dd6887df97Mike Reedvoid SkBitmapDevice::onSave() { 550c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.save(); 5517627fa51044e35dc21251f925b56f6dd6887df97Mike Reed} 5527627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5537627fa51044e35dc21251f925b56f6dd6887df97Mike Reedvoid SkBitmapDevice::onRestore() { 554c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.restore(); 5557627fa51044e35dc21251f925b56f6dd6887df97Mike Reed} 5567627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5577627fa51044e35dc21251f925b56f6dd6887df97Mike Reedvoid SkBitmapDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) { 558c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.clipRect(this->ctm(), rect, op, aa); 5597627fa51044e35dc21251f925b56f6dd6887df97Mike Reed} 5607627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5617627fa51044e35dc21251f925b56f6dd6887df97Mike Reedvoid SkBitmapDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { 562c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.clipRRect(this->ctm(), rrect, op, aa); 5637627fa51044e35dc21251f925b56f6dd6887df97Mike Reed} 5647627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5657627fa51044e35dc21251f925b56f6dd6887df97Mike Reedvoid SkBitmapDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) { 566c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.clipPath(this->ctm(), path, op, aa); 5677627fa51044e35dc21251f925b56f6dd6887df97Mike Reed} 5687627fa51044e35dc21251f925b56f6dd6887df97Mike Reed 5697627fa51044e35dc21251f925b56f6dd6887df97Mike Reedvoid SkBitmapDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) { 570c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkIPoint origin = this->getOrigin(); 571c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkRegion tmp; 572c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed const SkRegion* ptr = &rgn; 573c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed if (origin.fX | origin.fY) { 574c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed // translate from "global/canvas" coordinates to relative to this device 575c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed rgn.translate(-origin.fX, -origin.fY, &tmp); 576c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed ptr = &tmp; 577c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed } 578c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.clipRegion(*ptr, op); 579c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed} 580c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 581c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedvoid SkBitmapDevice::onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) { 582c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed fRCStack.setDeviceClipRestriction(mutableClipRestriction); 583d519d484949161df6d4b2ecadc282427cab532cfMike Reed if (!mutableClipRestriction->isEmpty()) { 584d519d484949161df6d4b2ecadc282427cab532cfMike Reed SkRegion rgn(*mutableClipRestriction); 585d519d484949161df6d4b2ecadc282427cab532cfMike Reed fRCStack.clipRegion(rgn, SkClipOp::kIntersect); 586d519d484949161df6d4b2ecadc282427cab532cfMike Reed } 587c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed} 588c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed 589a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedbool SkBitmapDevice::onClipIsAA() const { 590a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed const SkRasterClip& rc = fRCStack.rc(); 591a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed return !rc.isEmpty() && rc.isAA(); 592a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed} 593a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 594a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkBitmapDevice::onAsRgnClip(SkRegion* rgn) const { 595a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed const SkRasterClip& rc = fRCStack.rc(); 596a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed if (rc.isAA()) { 597a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed rgn->setRect(rc.getBounds()); 598a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed } else { 599a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed *rgn = rc.bwRgn(); 600a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed } 601a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed} 602a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 603c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reedvoid SkBitmapDevice::validateDevBounds(const SkIRect& drawClipBounds) { 604c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_DEBUG 605c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed const SkIRect& stackBounds = fRCStack.rc().getBounds(); 606c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed SkASSERT(drawClipBounds == stackBounds); 607c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif 6087627fa51044e35dc21251f925b56f6dd6887df97Mike Reed} 609a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 610a1361364e64138adda3dc5f71d50d7503838bb6dMike ReedSkBaseDevice::ClipType SkBitmapDevice::onGetClipType() const { 611a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed const SkRasterClip& rc = fRCStack.rc(); 612a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed if (rc.isEmpty()) { 613a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed return kEmpty_ClipType; 614a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed } else if (rc.isRect()) { 615a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed return kRect_ClipType; 616a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed } else { 617a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed return kComplex_ClipType; 618a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed } 619a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed} 620