SkDraw.cpp revision 57bfa0209e3379385b7ef6217cafb22ca83836c8
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7903dcb08b146cbaf81420a734a64692038b467cabungeman#define __STDC_LIMIT_MACROS 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 1083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby 1183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby#include "SkArenaAlloc.h" 12374772bd61951f01bf84fe17bf53d8867681c9aereed#include "SkBlendModePriv.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 16986480a71f4e860663ced7ad90a1fe346a164afbMike Reed#include "SkDevice.h" 171c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkDeviceLooper.h" 18e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#include "SkFindAndPlaceGlyph.h" 192211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com#include "SkFixed.h" 2000dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita#include "SkLocalMatrixShader.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 22f553e4e09cd2baf15fc041daab8a08bd46e352f0herb#include "SkMatrix.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathEffect.h" 25045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkRasterClip.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRasterizer.h" 27a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h" 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScan.h" 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" 3076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#include "SkString.h" 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStroke.h" 32435657fd62960ceffb1c3c63f63e836373560bc5halcanary#include "SkStrokeRec.h" 33f553e4e09cd2baf15fc041daab8a08bd46e352f0herb#include "SkTemplates.h" 34cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen#include "SkTextMapStateProc.h" 3532e5d97ccf60f859db063ebd6e903c362e625767reed@google.com#include "SkTLazy.h" 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 37559a8833f0eae4af37dc0ffc3ee97e1fb14817b1commit-bot@chromium.org#include "SkVertState.h" 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcShader.h" 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawProcs.h" 41ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com#include "SkMatrixUtils.h" 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define TRACE_BITMAP_DRAWS 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 45d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// Helper function to fix code gen bug on ARM64. 46d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// See SkFindAndPlaceGlyph.h for more details. 47d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbvoid FixGCC49Arm64Bug(int v) { } 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 49fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com/** Helper for allocating small blitters on the stack. 50fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com */ 5140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.comclass SkAutoBlitterChoose : SkNoncopyable { 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 531d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkAutoBlitterChoose() { 5496fcdcc219d2a0d3579719b84b28bede76efba64halcanary fBlitter = nullptr; 551d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 5641e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose(const SkPixmap& dst, const SkMatrix& matrix, 57126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkPaint& paint, bool drawCoverage = false) { 5883e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAlloc, drawCoverage); 59e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org } 60e59124ed1a62f1fec79679c38cabed622a756f75herb 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* operator->() { return fBlitter; } 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* get() const { return fBlitter; } 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6441e010cb901c0da9066c4df562030808c9ccd7f8reed void choose(const SkPixmap& dst, const SkMatrix& matrix, 6553f0959fc024c56dc55fe6bf86380127b59abec9krajcevski const SkPaint& paint, bool drawCoverage = false) { 661d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkASSERT(!fBlitter); 6783e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAlloc, drawCoverage); 681d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 691d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 71a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // Owned by fAllocator, which will handle the delete. 72a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkBlitter* fBlitter; 73a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator fAllocator; 7483e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby 7583e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby // FIXME - pick a good inline and number. 7683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby SkArenaAlloc fAlloc{1024}; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 78e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose) 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com/** 8140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com * Since we are providing the storage for the shader (to avoid the perf cost 8240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com * of calling new) we insist that in our destructor we can account for all 8340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com * owners of the shader. 8440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com */ 8540c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.comclass SkAutoBitmapShaderInstall : SkNoncopyable { 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 879c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint, 8896fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkMatrix* localMatrix = nullptr) 8940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com : fPaint(paint) /* makes a copy of the paint */ { 9083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby // TODO(herb): Move this over to SkArenaAlloc when arena alloc has a 9183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby // facility to return sk_sps. 928a21c9fe7f5fef9e87115defef27bd7218419f28reed fPaint.setShader(SkMakeBitmapShader(src, SkShader::kClamp_TileMode, 931ec04d9553af68b458c8dd6bd18d8c25ebd41d7areed SkShader::kClamp_TileMode, localMatrix, 941ec04d9553af68b458c8dd6bd18d8c25ebd41d7areed kNever_SkCopyPixelsMode, 951ec04d9553af68b458c8dd6bd18d8c25ebd41d7areed &fAllocator)); 9640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com // we deliberately left the shader with an owner-count of 2 978a21c9fe7f5fef9e87115defef27bd7218419f28reed fPaint.getShader()->ref(); 9840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkASSERT(2 == fPaint.getShader()->getRefCnt()); 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBitmapShaderInstall() { 102a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // since fAllocator will destroy shader, we insist that owners == 2 103a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkASSERT(2 == fPaint.getShader()->getRefCnt()); 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10596fcdcc219d2a0d3579719b84b28bede76efba64halcanary fPaint.setShader(nullptr); // unref the shader by 1 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 10940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com // return the new paint that has the shader applied 11040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com const SkPaint& paintWithShader() const { return fPaint; } 11182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 113a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // copy of caller's paint (which we then modify) 114a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkPaint fPaint; 115a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // Stores the shader. 116a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator fAllocator; 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 118e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall) 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 122f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDraw::SkDraw() { 123f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com sk_bzero(this, sizeof(*this)); 124f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 125f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1264bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.combool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const { 1274bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (fRC->isEmpty()) { 1284bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return false; 1294bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 1304bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1314bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkMatrix inverse; 1324bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (!fMatrix->invert(&inverse)) { 1334bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return false; 1344bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 1354bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1364bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkIRect devBounds = fRC->getBounds(); 1374bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com // outset to have slop for antialasing and hairlines 1384bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com devBounds.outset(1, 1); 1394bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com inverse.mapRect(localBounds, SkRect::Make(devBounds)); 1404bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return true; 1414bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com} 1424bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 1484516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(pixels, bytes); 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 154a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2)); 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 158a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1)); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(pixels, data, bytes); 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16541e010cb901c0da9066c4df562030808c9ccd7f8reedstatic BitmapXferProc ChooseBitmapXferProc(const SkPixmap& dst, const SkPaint& paint, 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t* data) { 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // todo: we can apply colorfilter up front if no shader, so we wouldn't 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to abort this fastpath 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getShader() || paint.getColorFilter()) { 17096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 173374772bd61951f01bf84fe17bf53d8867681c9aereed SkBlendMode mode = paint.getBlendMode(); 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor color = paint.getColor(); 175a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // collaps modes based on color... 177374772bd61951f01bf84fe17bf53d8867681c9aereed if (SkBlendMode::kSrcOver == mode) { 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned alpha = SkColorGetA(color); 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == alpha) { 180374772bd61951f01bf84fe17bf53d8867681c9aereed mode = SkBlendMode::kDst; 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (0xFF == alpha) { 182374772bd61951f01bf84fe17bf53d8867681c9aereed mode = SkBlendMode::kSrc; 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 185a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 187374772bd61951f01bf84fe17bf53d8867681c9aereed case SkBlendMode::kClear: 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Clear_BitmapXferProc\n"); 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Clear_BitmapXferProc; // ignore data 190374772bd61951f01bf84fe17bf53d8867681c9aereed case SkBlendMode::kDst: 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Dst_BitmapXferProc\n"); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Dst_BitmapXferProc; // ignore data 193374772bd61951f01bf84fe17bf53d8867681c9aereed case SkBlendMode::kSrc: { 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 195a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com should I worry about dithering for the lower depths? 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor pmc = SkPreMultiplyColor(color); 19841e010cb901c0da9066c4df562030808c9ccd7f8reed switch (dst.colorType()) { 19928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = pmc; 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D32_Src_BitmapXferProc\n"); 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D32_Src_BitmapXferProc; 205900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkPixel32ToPixel16(pmc); 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D16_Src_BitmapXferProc\n"); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D16_Src_BitmapXferProc; 211900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkGetPackedA32(pmc); 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return DA8_Src_BitmapXferProc; 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22841e010cb901c0da9066c4df562030808c9ccd7f8reedstatic void CallBitmapXferProc(const SkPixmap& dst, const SkIRect& rect, BitmapXferProc proc, 22941e010cb901c0da9066c4df562030808c9ccd7f8reed uint32_t procData) { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shiftPerPixel; 23141e010cb901c0da9066c4df562030808c9ccd7f8reed switch (dst.colorType()) { 23228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 2; 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 235900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 1; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 238900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 0; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2420c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("Can't use xferproc on this config"); 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24641e010cb901c0da9066c4df562030808c9ccd7f8reed uint8_t* pixels = (uint8_t*)dst.writable_addr(); 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pixels); 24841e010cb901c0da9066c4df562030808c9ccd7f8reed const size_t rowBytes = dst.rowBytes(); 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int widthBytes = rect.width() << shiftPerPixel; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip down to the first scanline and X position 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int scans = rect.height() - 1; scans >= 0; --scans) { 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(pixels, widthBytes, procData); 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rowBytes; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPaint(const SkPaint& paint) const { 260f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 262045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devRect; 26741e010cb901c0da9066c4df562030808c9ccd7f8reed devRect.set(0, 0, fDst.width(), fDst.height()); 268a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 269045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 270045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com /* If we don't have a shader (i.e. we're just a solid color) we may 271045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com be faster to operate directly on the device bitmap, rather than invoking 272045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a blitter. Esp. true for xfermodes, which require a colorshader to be 273045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com present, which is just redundant work. Since we're drawing everywhere 274045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com in the clip, we don't have to worry about antialiasing. 275045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 276045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint32_t procData = 0; // to avoid the warning 27741e010cb901c0da9066c4df562030808c9ccd7f8reed BitmapXferProc proc = ChooseBitmapXferProc(fDst, paint, &procData); 278045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (proc) { 279045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (D_Dst_BitmapXferProc == proc) { // nothing to do 280045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 281045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 282a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 283045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRegion::Iterator iter(fRC->bwRgn()); 284045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 28541e010cb901c0da9066c4df562030808c9ccd7f8reed CallBitmapXferProc(fDst, iter.rect(), proc, procData); 286045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 287045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 288045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 291045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 292045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // normal case: use a blitter 29341e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 294045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(devRect, *fRC, blitter.get()); 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct PtProcRec { 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::PointMode fMode; 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* fClip; 303045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip* fRC; 304a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // computed values 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fRadius; 307a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 312045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip*); 313045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Proc chooseProc(SkBlitter** blitter); 314045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 315045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 316045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper fWrapper; 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec.fClip->isRect()); 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rec.fClip->getBounds(); 323a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3252d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3262d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint devPts[], int count, 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 336045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rec.fRC->isRect()); 337045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 33941e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 34041e010cb901c0da9066c4df562030808c9ccd7f8reed SkASSERT(dst); 341c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 34241e010cb901c0da9066c4df562030808c9ccd7f8reed uint16_t* addr = dst->writable_addr16(0, 0); 34341e010cb901c0da9066c4df562030808c9ccd7f8reed size_t rb = dst->rowBytes(); 344c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3462d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3472d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3542d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.comstatic void bw_pt_rect_32_hair_proc(const PtProcRec& rec, 3552d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkPoint devPts[], int count, 3562d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkBlitter* blitter) { 3572d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(rec.fRC->isRect()); 3582d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3592d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com uint32_t value; 36041e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 36141e010cb901c0da9066c4df562030808c9ccd7f8reed SkASSERT(dst); 362c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 36341e010cb901c0da9066c4df562030808c9ccd7f8reed SkPMColor* addr = dst->writable_addr32(0, 0); 36441e010cb901c0da9066c4df562030808c9ccd7f8reed size_t rb = dst->rowBytes(); 365c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3662d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com for (int i = 0; i < count; i++) { 3672d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3682d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3692d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (r.contains(x, y)) { 3702d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com ((SkPMColor*)((char*)addr + y * rb))[x] = value; 3712d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3722d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3732d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com} 3742d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 378e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 379e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec.fClip->contains(x, y)) { 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3895dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter); 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3955dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairLine(devPts, count, *rec.fRC, blitter); 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// aa versions 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 4035dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter); 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4095dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter); 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 420c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 426c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 427045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillXRect(r, *rec.fRC, blitter); 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 437a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 443a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 444045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::AntiFillXRect(r, *rec.fRC, blitter); 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 448b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com// If this guy returns true, then chooseProc() must return a valid proc 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 450045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMatrix* matrix, const SkRasterClip* rc) { 4513ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang if ((unsigned)mode > (unsigned)SkCanvas::kPolygon_PointMode) { 4523ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang return false; 4533ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang } 4543ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect()) { 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == width) { 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 46296fcdcc219d2a0d3579719b84b28bede76efba64halcanary fClip = nullptr; 463045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 4642d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com fRadius = SK_FixedHalf; 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 467b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com if (paint.getStrokeCap() != SkPaint::kRound_Cap && 4689f2251c73ed6f417dd1057d487bf523e04488440robertphillips matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) { 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = matrix->get(SkMatrix::kMScaleX); 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = matrix->get(SkMatrix::kMScaleY); 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(sx - sy)) { 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sx < 0) { 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sx = -sx; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 47896fcdcc219d2a0d3579719b84b28bede76efba64halcanary fClip = nullptr; 479045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 480a99b6ceff92183b424634f2e7276b9ea1d59e69dMike Reed fRadius = SkScalarToFixed(width * sx) >> 1; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 487045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comPtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 48896fcdcc219d2a0d3579719b84b28bede76efba64halcanary Proc proc = nullptr; 489a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 490045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = *blitterPtr; 491045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 492045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fRC->bwRgn(); 493045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 494045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fWrapper.init(*fRC, blitter); 495045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fWrapper.getRgn(); 496045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = fWrapper.getBlitter(); 497045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *blitterPtr = blitter; 498045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 499045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for our arrays 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == SkCanvas::kPoints_PointMode); 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == SkCanvas::kLines_PointMode); 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(2 == SkCanvas::kPolygon_PointMode); 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5062d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fPaint->isAntiAlias()) { 5072d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (0 == fPaint->getStrokeWidth()) { 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const Proc gAAProcs[] = { 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gAAProcs[fMode]; 5122d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 5132d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(SkCanvas::kPoints_PointMode == fMode); 5142d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = aa_square_proc; 5152d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 5162d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else { // BW 5172d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fRadius <= SK_FixedHalf) { // small radii and hairline 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 52041e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* bm = blitter->justAnOpaqueColor(&value); 521900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bm && kRGB_565_SkColorType == bm->colorType()) { 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_16_hair_proc; 52328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org } else if (bm && kN32_SkColorType == bm->colorType()) { 5242d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = bw_pt_rect_32_hair_proc; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_hair_proc; 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static Proc gBWProcs[] = { 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gBWProcs[fMode]; 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_square_proc; 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return proc; 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// each of these costs 8-bytes of stack space, so don't make it too large 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// must be even for lines/polygon to work 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_DEV_PTS 32 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 546f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkPoint pts[], const SkPaint& paint, 547f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com bool forceUseDevice) const { 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're in lines mode, force count to be even 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kLines_PointMode == mode) { 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count &= ~(size_t)1; 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 556a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 55796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(pts != nullptr); 558f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 559a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 561045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PtProcRec rec; 566045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) { 56741e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint devPts[MAX_DEV_PTS]; 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* bltr = blitter.get(); 572045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com PtProcRec::Proc proc = rec.chooseProc(&bltr); 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we have to back up subsequent passes if we're in polygon mode 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 575a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 577a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org int n = SkToInt(count); 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n > MAX_DEV_PTS) { 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = MAX_DEV_PTS; 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->mapPoints(devPts, pts, n); 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(rec, devPts, n, bltr); 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts += n - backup; 584a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org SkASSERT(SkToInt(count) >= n); 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += backup; 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count != 0); 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPoints_PointMode: { 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // temporarily mark the paint as filling. 59440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint newPaint(paint); 59540c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com newPaint.setStyle(SkPaint::kFill_Style); 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 59740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkScalar width = newPaint.getStrokeWidth(); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar radius = SkScalarHalf(width); 599a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 60040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix preMatrix; 6037ef849d45a4de02697697ea213bfae7c215a0c38mtklein 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addCircle(0, 0, radius); 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com preMatrix.setTranslate(pts[i].fX, pts[i].fY); 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pass true for the last point, since we can modify 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // then path then 609b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile((count-1) == i); 610f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 61140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fDevice->drawPath(*this, path, newPaint, &preMatrix, 612f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com (count-1) == i); 613f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 61440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawPath(path, newPaint, &preMatrix, 61540c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com (count-1) == i); 616f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 620a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = pts[i].fX - radius; 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = pts[i].fY - radius; 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = r.fLeft + width; 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = r.fTop + width; 626f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 62740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fDevice->drawRect(*this, r, newPaint); 628f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 62940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawRect(r, newPaint); 630f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kLines_PointMode: 63649f085dddff10473b6ebf832a974288300224e60bsalomon if (2 == count && paint.getPathEffect()) { 637629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // most likely a dashed line - see if it is one of the ones 638629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // we can accelerate 639629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkStrokeRec rec(paint); 6406d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkPathEffect::PointData pointData; 641629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 642629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPath path; 643629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.moveTo(pts[0]); 644629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.lineTo(pts[1]); 645629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6464bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect = SkRect::Make(fRC->getBounds()); 6474024f32d99b63a599c544a49f526e53c25135159skia.committer@gmail.com 6484bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (paint.getPathEffect()->asPoints(&pointData, path, rec, 6494bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com *fMatrix, &cullRect)) { 6506d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // 'asPoints' managed to find some fast path 6516d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 652629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPaint newP(paint); 65396fcdcc219d2a0d3579719b84b28bede76efba64halcanary newP.setPathEffect(nullptr); 654935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com newP.setStyle(SkPaint::kFill_Style); 655629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6566d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fFirst.isEmpty()) { 6576d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6586d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawPath(*this, pointData.fFirst, newP); 6596d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6606d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fFirst, newP); 6616d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 662629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 6636d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6646d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fLast.isEmpty()) { 6656d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6666d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawPath(*this, pointData.fLast, newP); 6676d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6686d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fLast, newP); 6696d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6706d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6716d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6726d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (pointData.fSize.fX == pointData.fSize.fY) { 6736d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line can just be drawn as points 6746d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth())); 6756d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6766d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) { 6776d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kRound_Cap); 6786d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6796d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kButt_Cap); 6806d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6816d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6826d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6837a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com fDevice->drawPoints(*this, 6846d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkCanvas::kPoints_PointMode, 6856d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 6866d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 6876d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP); 6886d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6896d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPoints(SkCanvas::kPoints_PointMode, 6906d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 6916d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 6926d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP, 6936d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com forceUseDevice); 6946d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6956d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com break; 696935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } else { 6976d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line must be drawn as rects 6987a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag & 6996d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fFlags)); 7006d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 7016d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkRect r; 7026d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 7036d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com for (int i = 0; i < pointData.fNumPoints; ++i) { 7046d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com r.set(pointData.fPoints[i].fX - pointData.fSize.fX, 7056d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY - pointData.fSize.fY, 7066d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fX + pointData.fSize.fX, 7076d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY + pointData.fSize.fY); 7086d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 7096d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawRect(*this, r, newP); 7106d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 7116d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawRect(r, newP); 7126d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 7136d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 714935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } 7156d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 716629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com break; 717629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 718629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 719629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // couldn't take fast path so fall through! 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPolygon_PointMode: { 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= 1; 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setStyle(SkPaint::kStroke_Style); 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 726b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile(true); 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i += inc) { 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(pts[i]); 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.lineTo(pts[i+1]); 730f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 73196fcdcc219d2a0d3579719b84b28bede76efba64halcanary fDevice->drawPath(*this, path, p, nullptr, true); 732f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 73396fcdcc219d2a0d3579719b84b28bede76efba64halcanary this->drawPath(path, p, nullptr, true); 734f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.rewind(); 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7431a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalitastatic inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) { 7441a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkASSERT(matrix.rectStaysRect()); 7451a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkASSERT(SkPaint::kFill_Style != paint.getStyle()); 7461a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 7471a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkVector size; 7481a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 7491a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita matrix.mapVectors(&size, &pt, 1); 7501a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY)); 7511a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita} 7521a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 753761fb62b0eb174783316d2a8b933fba896ca6355reed@google.comstatic bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 754761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com SkPoint* strokeSize) { 755761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 756761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com paint.getStrokeMiter() < SK_ScalarSqrt2) { 757761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return false; 758761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com } 759fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7601a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita *strokeSize = compute_stroke_size(paint, matrix); 761761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return true; 7627ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org} 7637ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 76462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.comSkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 76562ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const SkMatrix& matrix, 76662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint* strokeSize) { 7677ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org RectType rtype; 7687ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org const SkScalar width = paint.getStrokeWidth(); 76962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const bool zeroWidth = (0 == width); 7707ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::Style style = paint.getStyle(); 771fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7727ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 7737ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org style = SkPaint::kFill_Style; 7747ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 775fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getMaskFilter() || 77762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com paint.getRasterizer() || !matrix.rectStaysRect() || 7787ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::kStrokeAndFill_Style == style) { 77962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com rtype = kPath_RectType; 78062ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (SkPaint::kFill_Style == style) { 7817ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kFill_RectType; 7827ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else if (zeroWidth) { 7837ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kHair_RectType; 78462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (easy_rect_join(paint, matrix, strokeSize)) { 7857ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kStroke_RectType; 7867ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else { 7877ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kPath_RectType; 7887ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 78962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return rtype; 79062ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com} 79162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 7927324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic const SkPoint* rect_points(const SkRect& r) { 793fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<const SkPoint*>(&r); 7947324415759fe0c5a0902877b664aa942a89bd940reed@google.com} 7957324415759fe0c5a0902877b664aa942a89bd940reed@google.com 7967324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic SkPoint* rect_points(SkRect& r) { 797fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<SkPoint*>(&r); 79840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com} 79940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com 8000393912de72bc3d8b3640c122c53470dd0da1e6dreedvoid SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, 8010393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkMatrix* paintMatrix, const SkRect* postPaintRect) const { 80262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkDEBUGCODE(this->validate();) 8037ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 80462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com // nothing to draw 805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 80662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return; 80762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } 80862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 8090393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkMatrix* matrix; 8100393912de72bc3d8b3640c122c53470dd0da1e6dreed SkMatrix combinedMatrixStorage; 8110393912de72bc3d8b3640c122c53470dd0da1e6dreed if (paintMatrix) { 8120393912de72bc3d8b3640c122c53470dd0da1e6dreed SkASSERT(postPaintRect); 8130393912de72bc3d8b3640c122c53470dd0da1e6dreed combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix); 8140393912de72bc3d8b3640c122c53470dd0da1e6dreed matrix = &combinedMatrixStorage; 8150393912de72bc3d8b3640c122c53470dd0da1e6dreed } else { 8160393912de72bc3d8b3640c122c53470dd0da1e6dreed SkASSERT(!postPaintRect); 8170393912de72bc3d8b3640c122c53470dd0da1e6dreed matrix = fMatrix; 8180393912de72bc3d8b3640c122c53470dd0da1e6dreed } 8190393912de72bc3d8b3640c122c53470dd0da1e6dreed 82062ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint strokeSize; 82162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 82262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 8237ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if (kPath_RectType == rtype) { 8240393912de72bc3d8b3640c122c53470dd0da1e6dreed SkDraw draw(*this); 8250393912de72bc3d8b3640c122c53470dd0da1e6dreed if (paintMatrix) { 8260393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.fMatrix = matrix; 8270393912de72bc3d8b3640c122c53470dd0da1e6dreed } 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmp; 8290393912de72bc3d8b3640c122c53470dd0da1e6dreed tmp.addRect(prePaintRect); 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setFillType(SkPath::kWinding_FillType); 83196fcdcc219d2a0d3579719b84b28bede76efba64halcanary draw.drawPath(tmp, paint, nullptr, true); 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8350393912de72bc3d8b3640c122c53470dd0da1e6dreed SkRect devRect; 8361a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect; 8371a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita // skip the paintMatrix when transforming the rect by the CTM 8381a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2); 8397324415759fe0c5a0902877b664aa942a89bd940reed@google.com devRect.sort(); 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for the quick exit, before we build a blitter 8421a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkRect bbox = devRect; 8431c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.getStyle() != SkPaint::kFill_Style) { 8441c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // extra space for hairlines 845b3eba478d5bed5fb2b5f0f224738c8c292cebf36george if (paint.getStrokeWidth() == 0) { 8461a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita bbox.outset(1, 1); 847b3eba478d5bed5fb2b5f0f224738c8c292cebf36george } else { 8481a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita // For kStroke_RectType, strokeSize is already computed. 8491a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita const SkPoint& ssize = (kStroke_RectType == rtype) 8501a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita ? strokeSize 8511a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita : compute_stroke_size(paint, *fMatrix); 8521a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y())); 853b3eba478d5bed5fb2b5f0f224738c8c292cebf36george } 8541c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8551a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 8561a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkIRect ir = bbox.roundOut(); 8571c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (fRC->quickReject(ir)) { 8581c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com return; 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 86141e010cb901c0da9066c4df562030808c9ccd7f8reed SkDeviceLooper looper(fDst, *fRC, ir, paint.isAntiAlias()); 8621c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com while (looper.next()) { 8631c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkRect localDevRect; 8641c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com looper.mapRect(&localDevRect, devRect); 8651c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkMatrix localMatrix; 8660393912de72bc3d8b3640c122c53470dd0da1e6dreed looper.mapMatrix(&localMatrix, *matrix); 8671c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 86841e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitterStorage(looper.getPixmap(), localMatrix, paint); 8691c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com const SkRasterClip& clip = looper.getRC(); 8701c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkBlitter* blitter = blitterStorage.get(); 8711c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 8721c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 8731c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // case we are also hairline (if we've gotten to here), which devolves to 8741c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // effectively just kFill 8751c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com switch (rtype) { 8761c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kFill_RectType: 8771c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8781c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFillRect(localDevRect, clip, blitter); 8791c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8801c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FillRect(localDevRect, clip, blitter); 8811c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8821c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8831c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kStroke_RectType: 8841c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8851c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); 8861c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8871c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); 8881c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8891c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8901c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kHair_RectType: 8911c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8921c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiHairRect(localDevRect, clip, blitter); 8931c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8941c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::HairRect(localDevRect, clip, blitter); 8951c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8961c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8971c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com default: 8981c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkDEBUGFAIL("bad rtype"); 8991c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (srcM.fBounds.isEmpty()) { 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9080a60b3d32eae945688b69599f11679662657f751bungeman@google.com const SkMask* mask = &srcM; 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9100a60b3d32eae945688b69599f11679662657f751bungeman@google.com SkMask dstM; 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getMaskFilter() && 912e80eb928ba0248a5a5dea6e1f0005aa08ecf8740robertphillips paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, nullptr)) { 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask = &dstM; 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 91502f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com SkAutoMaskFreeImage ami(dstM.fImage); 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 91741e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 918045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = blitterChooser.get(); 919045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrapper; 921045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRegion* clipRgn; 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 923045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 924045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &fRC->bwRgn(); 925045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 926045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrapper.init(*fRC, blitter); 927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &wrapper.getRgn(); 928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrapper.getBlitter(); 929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter->blitMaskRegion(*mask, *clipRgn); 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 933ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.comstatic SkScalar fast_len(const SkVector& vec) { 934ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar x = SkScalarAbs(vec.fX); 935ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar y = SkScalarAbs(vec.fY); 936ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (x < y) { 937ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkTSwap(x, y); 938ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 939ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return x + SkScalarHalf(y); 940ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 941ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 942e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.orgbool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, 943e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkScalar* coverage) { 944e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkASSERT(strokeWidth > 0); 945e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org // We need to try to fake a thick-stroke with a modulated hairline. 946ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 9478d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (matrix.hasPerspective()) { 948ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 949ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 950ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 951ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkVector src[2], dst[2]; 952ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[0].set(strokeWidth, 0); 953ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[1].set(0, strokeWidth); 954ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com matrix.mapVectors(dst, src, 2); 955ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len0 = fast_len(dst[0]); 956ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len1 = fast_len(dst[1]); 957652807bbc8c57e5fa9622126b51fd369f5c67935agl@chromium.org if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 95849f085dddff10473b6ebf832a974288300224e60bsalomon if (coverage) { 959e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org *coverage = SkScalarAve(len0, len1); 960e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 961ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return true; 962ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 963ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 964ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 965ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 966a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comvoid SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { 967a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkDEBUGCODE(this->validate()); 968a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 969a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (fRC->isEmpty()) { 970a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; 971a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 972a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 973a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com { 974a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: Investigate optimizing these options. They are in the same 975a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // order as SkDraw::drawPath, which handles each case. It may be 976a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // that there is no way to optimize for these using the SkRRect path. 977a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkScalar coverage; 978a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { 979a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 980a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 981a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 982a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 983a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 984a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 985a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 986a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getRasterizer()) { 987a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 988a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 989a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 990a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 991a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getMaskFilter()) { 992a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Transform the rrect into device space. 993a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRRect devRRect; 994a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (rrect.transform(*fMatrix, &devRRect)) { 99541e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 996055e192adc0072ae2548ef5431ceee652945f9c2bsalomon if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get())) { 997a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; // filterRRect() called the blitter, so we're done 998a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 999a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1000a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1001a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 1002a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comDRAW_PATH: 1003a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Now fall back to the default case of using a path. 1004a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPath path; 1005a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com path.addRRect(rrect); 100696fcdcc219d2a0d3579719b84b28bede76efba64halcanary this->drawPath(path, paint, nullptr, true); 1007a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 1008a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 10091a7eb266644d2e1b0968dbca606ca0a91903419dcaryclarkSkScalar SkDraw::ComputeResScaleForStroking(const SkMatrix& matrix) { 101005d9044de4f1c6e791df66a425638752daac4c6breed if (!matrix.hasPerspective()) { 101105d9044de4f1c6e791df66a425638752daac4c6breed SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]); 101205d9044de4f1c6e791df66a425638752daac4c6breed SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]); 101305d9044de4f1c6e791df66a425638752daac4c6breed if (SkScalarsAreFinite(sx, sy)) { 1014a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman SkScalar scale = SkTMax(sx, sy); 1015a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman if (scale > 0) { 1016a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman return scale; 1017a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman } 101805d9044de4f1c6e791df66a425638752daac4c6breed } 101905d9044de4f1c6e791df66a425638752daac4c6breed } 102005d9044de4f1c6e791df66a425638752daac4c6breed return 1; 102105d9044de4f1c6e791df66a425638752daac4c6breed} 102205d9044de4f1c6e791df66a425638752daac4c6breed 102382595b6fa4733e1525f357bdcac22db058790550reedvoid SkDraw::drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawCoverage, 102482595b6fa4733e1525f357bdcac22db058790550reed SkBlitter* customBlitter, bool doFill) const { 102501a2ff8a325e17221b139968e337413df0c2e60creed // Do a conservative quick-reject test, since a looper or other modifier may have moved us 102601a2ff8a325e17221b139968e337413df0c2e60creed // out of range. 102701a2ff8a325e17221b139968e337413df0c2e60creed if (!devPath.isInverseFillType()) { 102801a2ff8a325e17221b139968e337413df0c2e60creed // If we're a H or V line, our bounds will be empty. So we bloat here just so we don't 102901a2ff8a325e17221b139968e337413df0c2e60creed // appear empty to the intersects call. This also gives us slop in case we're antialiasing 103001a2ff8a325e17221b139968e337413df0c2e60creed SkRect pathBounds = devPath.getBounds().makeOutset(1, 1); 103101a2ff8a325e17221b139968e337413df0c2e60creed 103201a2ff8a325e17221b139968e337413df0c2e60creed if (paint.getMaskFilter()) { 103301a2ff8a325e17221b139968e337413df0c2e60creed paint.getMaskFilter()->computeFastBounds(pathBounds, &pathBounds); 103401a2ff8a325e17221b139968e337413df0c2e60creed 103501a2ff8a325e17221b139968e337413df0c2e60creed // Need to outset the path to work-around a bug in blurmaskfilter. When that is fixed 103601a2ff8a325e17221b139968e337413df0c2e60creed // we can remove this hack. See skbug.com/5542 103701a2ff8a325e17221b139968e337413df0c2e60creed pathBounds.outset(7, 7); 103801a2ff8a325e17221b139968e337413df0c2e60creed } 103901a2ff8a325e17221b139968e337413df0c2e60creed 104001a2ff8a325e17221b139968e337413df0c2e60creed // Now compare against the clip's bounds 104101a2ff8a325e17221b139968e337413df0c2e60creed if (!SkRect::Make(fRC->getBounds()).intersects(pathBounds)) { 104201a2ff8a325e17221b139968e337413df0c2e60creed return; 104301a2ff8a325e17221b139968e337413df0c2e60creed } 104401a2ff8a325e17221b139968e337413df0c2e60creed } 104501a2ff8a325e17221b139968e337413df0c2e60creed 104682595b6fa4733e1525f357bdcac22db058790550reed SkBlitter* blitter = nullptr; 104782595b6fa4733e1525f357bdcac22db058790550reed SkAutoBlitterChoose blitterStorage; 104882595b6fa4733e1525f357bdcac22db058790550reed if (nullptr == customBlitter) { 104982595b6fa4733e1525f357bdcac22db058790550reed blitterStorage.choose(fDst, *fMatrix, paint, drawCoverage); 105082595b6fa4733e1525f357bdcac22db058790550reed blitter = blitterStorage.get(); 105182595b6fa4733e1525f357bdcac22db058790550reed } else { 105282595b6fa4733e1525f357bdcac22db058790550reed blitter = customBlitter; 105382595b6fa4733e1525f357bdcac22db058790550reed } 105482595b6fa4733e1525f357bdcac22db058790550reed 105582595b6fa4733e1525f357bdcac22db058790550reed if (paint.getMaskFilter()) { 105682595b6fa4733e1525f357bdcac22db058790550reed SkStrokeRec::InitStyle style = doFill ? SkStrokeRec::kFill_InitStyle 105782595b6fa4733e1525f357bdcac22db058790550reed : SkStrokeRec::kHairline_InitStyle; 105882595b6fa4733e1525f357bdcac22db058790550reed if (paint.getMaskFilter()->filterPath(devPath, *fMatrix, *fRC, blitter, style)) { 105982595b6fa4733e1525f357bdcac22db058790550reed return; // filterPath() called the blitter, so we're done 106082595b6fa4733e1525f357bdcac22db058790550reed } 106182595b6fa4733e1525f357bdcac22db058790550reed } 106282595b6fa4733e1525f357bdcac22db058790550reed 106382595b6fa4733e1525f357bdcac22db058790550reed void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 106482595b6fa4733e1525f357bdcac22db058790550reed if (doFill) { 106582595b6fa4733e1525f357bdcac22db058790550reed if (paint.isAntiAlias()) { 106682595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiFillPath; 106782595b6fa4733e1525f357bdcac22db058790550reed } else { 106882595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::FillPath; 106982595b6fa4733e1525f357bdcac22db058790550reed } 107082595b6fa4733e1525f357bdcac22db058790550reed } else { // hairline 107182595b6fa4733e1525f357bdcac22db058790550reed if (paint.isAntiAlias()) { 107282595b6fa4733e1525f357bdcac22db058790550reed switch (paint.getStrokeCap()) { 107382595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kButt_Cap: 107482595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiHairPath; 107582595b6fa4733e1525f357bdcac22db058790550reed break; 107682595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kSquare_Cap: 107782595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiHairSquarePath; 107882595b6fa4733e1525f357bdcac22db058790550reed break; 107982595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kRound_Cap: 108082595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiHairRoundPath; 108182595b6fa4733e1525f357bdcac22db058790550reed break; 108282595b6fa4733e1525f357bdcac22db058790550reed default: 108382595b6fa4733e1525f357bdcac22db058790550reed proc SK_INIT_TO_AVOID_WARNING; 108482595b6fa4733e1525f357bdcac22db058790550reed SkDEBUGFAIL("unknown paint cap type"); 108582595b6fa4733e1525f357bdcac22db058790550reed } 108682595b6fa4733e1525f357bdcac22db058790550reed } else { 108782595b6fa4733e1525f357bdcac22db058790550reed switch (paint.getStrokeCap()) { 108882595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kButt_Cap: 108982595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::HairPath; 109082595b6fa4733e1525f357bdcac22db058790550reed break; 109182595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kSquare_Cap: 109282595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::HairSquarePath; 109382595b6fa4733e1525f357bdcac22db058790550reed break; 109482595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kRound_Cap: 109582595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::HairRoundPath; 109682595b6fa4733e1525f357bdcac22db058790550reed break; 109782595b6fa4733e1525f357bdcac22db058790550reed default: 109882595b6fa4733e1525f357bdcac22db058790550reed proc SK_INIT_TO_AVOID_WARNING; 109982595b6fa4733e1525f357bdcac22db058790550reed SkDEBUGFAIL("unknown paint cap type"); 110082595b6fa4733e1525f357bdcac22db058790550reed } 110182595b6fa4733e1525f357bdcac22db058790550reed } 110282595b6fa4733e1525f357bdcac22db058790550reed } 110382595b6fa4733e1525f357bdcac22db058790550reed proc(devPath, *fRC, blitter); 110482595b6fa4733e1525f357bdcac22db058790550reed} 110582595b6fa4733e1525f357bdcac22db058790550reed 110632e5d97ccf60f859db063ebd6e903c362e625767reed@google.comvoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 1107126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkMatrix* prePathMatrix, bool pathIsMutable, 110853f0959fc024c56dc55fe6bf86380127b59abec9krajcevski bool drawCoverage, SkBlitter* customBlitter) const { 1109f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* pathPtr = (SkPath*)&origSrcPath; 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool doFill = true; 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmpPath; 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmpMatrix; 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 1121b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth tmpPath.setIsVolatile(true); 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prePathMatrix) { 112432e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style || 112532e5d97ccf60f859db063ebd6e903c362e625767reed@google.com origPaint.getRasterizer()) { 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* result = pathPtr; 1127a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!pathIsMutable) { 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = &tmpPath; 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathIsMutable = true; 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*prePathMatrix, result); 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = result; 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 113592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmpMatrix.setConcat(*matrix, *prePathMatrix); 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix = &tmpMatrix; 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // at this point we're done with prePathMatrix 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 1141a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11425dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1143a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1144ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com { 1145dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com SkScalar coverage; 1146dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 1147dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SK_Scalar1 == coverage) { 11485dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setStrokeWidth(0); 1149374772bd61951f01bf84fe17bf53d8867681c9aereed } else if (SkBlendMode_SupportsCoverageAsAlpha(origPaint.getBlendMode())) { 1150dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com U8CPU newAlpha; 1151dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#if 0 1152dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = SkToU8(SkScalarRoundToInt(coverage * 1153dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com origPaint.getAlpha())); 1154dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#else 1155dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // this is the old technique, which we preserve for now so 1156dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // we don't change previous results (testing) 1157dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // the new way seems fine, its just (a tiny bit) different 1158a99b6ceff92183b424634f2e7276b9ea1d59e69dMike Reed int scale = (int)(coverage * 256); 1159dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = origPaint.getAlpha() * scale >> 8; 1160dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#endif 11615dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkPaint* writablePaint = paint.writable(); 11625dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setStrokeWidth(0); 11635dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setAlpha(newAlpha); 1164dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com } 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1167a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 116832e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 11694bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect; 117096fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkRect* cullRectPtr = nullptr; 11714bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (this->computeConservativeLocalClipBounds(&cullRect)) { 11724bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com cullRectPtr = &cullRect; 11734bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 117405d9044de4f1c6e791df66a425638752daac4c6breed doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr, 11751a7eb266644d2e1b0968dbca606ca0a91903419dcaryclark ComputeResScaleForStroking(*fMatrix)); 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = &tmpPath; 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1178a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 117932e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()) { 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 118132e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()->rasterize(*pathPtr, *matrix, 1182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com &fRC->getBounds(), paint->getMaskFilter(), &mask, 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 118432e5d97ccf60f859db063ebd6e903c362e625767reed@google.com this->drawDevMask(mask, *paint); 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(mask.fImage); 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // avoid possibly allocating a new path in transform if we can 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform the path into device space 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*matrix, devPathPtr); 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 119682595b6fa4733e1525f357bdcac22db058790550reed this->drawDevPath(*devPathPtr, *paint, drawCoverage, customBlitter, doFill); 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 119982595b6fa4733e1525f357bdcac22db058790550reedvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, const SkPaint& paint) const { 1200900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType); 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1202c7e211acd0c9201688de7ff0c9a2271c67440adffmalita if (SkTreatAsSprite(*fMatrix, bitmap.dimensions(), paint)) { 1203e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(fMatrix->getTranslateX()); 1204e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(fMatrix->getTranslateY()); 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 120692fc2ae58331662ec411a048686cb4801e0a909areed SkAutoPixmapUnlock result; 120792fc2ae58331662ec411a048686cb4801e0a909areed if (!bitmap.requestLock(&result)) { 1208a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com return; 1209a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com } 121092fc2ae58331662ec411a048686cb4801e0a909areed const SkPixmap& pmap = result.pixmap(); 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 121292fc2ae58331662ec411a048686cb4801e0a909areed mask.fBounds.set(ix, iy, ix + pmap.width(), iy + pmap.height()); 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 121492fc2ae58331662ec411a048686cb4801e0a909areed mask.fRowBytes = SkToU32(pmap.rowBytes()); 121592fc2ae58331662ec411a048686cb4801e0a909areed // fImage is typed as writable, but in this case it is used read-only 121692fc2ae58331662ec411a048686cb4801e0a909areed mask.fImage = (uint8_t*)pmap.addr8(0, 0); 1217a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // need to xform the bitmap first 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 1222a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapRect(&r); 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&mask.fBounds); 1227a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // set the mask's bounds to the transformed bitmap-bounds, 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clipped to the actual device 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devBounds; 123241e010cb901c0da9066c4df562030808c9ccd7f8reed devBounds.set(0, 0, fDst.width(), fDst.height()); 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need intersect(l, t, r, b) on irect 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!mask.fBounds.intersect(devBounds)) { 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1238543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1241543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask.computeImageSize(); 1242543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 1243543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // the mask is too big to allocated, draw nothing 1244543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return; 1245543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // allocate (and clear) our temp buffer to hold the transformed bitmap 1248565901db954c231840750ea955ed31b820b9ade8scroggo SkAutoTMalloc<uint8_t> storage(size); 1249565901db954c231840750ea955ed31b820b9ade8scroggo mask.fImage = storage.get(); 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask.fImage, 0, size); 1251a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now draw our bitmap(src) into mask(dst), transformed by the matrix 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap device; 1255a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()), 1256a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org mask.fImage, mask.fRowBytes); 1257a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas c(device); 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need the unclipped top/left for the translate 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.translate(-SkIntToScalar(mask.fBounds.fLeft), 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.concat(*fMatrix); 12633469c76c40790b409621fd7eff34f56240718549reed@android.com 12643469c76c40790b409621fd7eff34f56240718549reed@android.com // We can't call drawBitmap, or we'll infinitely recurse. Instead 1265fb12c3e6ba84f95dc15fbaddc239dede0ba1d60ereed@android.com // we manually build a shader and draw that into our new mask 12663469c76c40790b409621fd7eff34f56240718549reed@android.com SkPaint tmpPaint; 12673469c76c40790b409621fd7eff34f56240718549reed@android.com tmpPaint.setFlags(paint.getFlags()); 126866a96d07d5583cc018cb70127bd5483799b69d0ebrianosman tmpPaint.setFilterQuality(paint.getFilterQuality()); 126940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkAutoBitmapShaderInstall install(bitmap, tmpPaint); 12703469c76c40790b409621fd7eff34f56240718549reed@android.com SkRect rr; 12713469c76c40790b409621fd7eff34f56240718549reed@android.com rr.set(0, 0, SkIntToScalar(bitmap.width()), 12723469c76c40790b409621fd7eff34f56240718549reed@android.com SkIntToScalar(bitmap.height())); 127340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com c.drawRect(rr, install.paintWithShader()); 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1279045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& srcR) { 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect dstR; 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.mapRect(&dstR, srcR); 1283b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed return c.quickReject(dstR.roundOut()); 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1286045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip, 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width, int height) { 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return clipped_out(matrix, clip, r); 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1293c240e719b2bebd3711ade4e6fe056921aa7b0521reedstatic bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, const SkPixmap& pmap) { 1294c240e719b2bebd3711ade4e6fe056921aa7b0521reed return clip.isBW() || clip.quickContains(x, y, x + pmap.width(), y + pmap.height()); 1295045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1296045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 12980393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkRect* dstBounds, const SkPaint& origPaint) const { 1299f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1302045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1304900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1307a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1308f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1309f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita if (origPaint.getStyle() != SkPaint::kFill_Style) { 1310f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita paint.writable()->setStyle(SkPaint::kFill_Style); 1311f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita } 1312a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 131492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org matrix.setConcat(*fMatrix, prematrix); 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1316045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) { 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1320c7e211acd0c9201688de7ff0c9a2271c67440adffmalita if (bitmap.colorType() != kAlpha_8_SkColorType 1321f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita && SkTreatAsSprite(matrix, bitmap.dimensions(), *paint)) { 1322f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1323f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // It is safe to call lock pixels now, since we know the matrix is 1324f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // (more or less) identity. 1325f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1326c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkAutoPixmapUnlock unlocker; 1327c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (!bitmap.requestLock(&unlocker)) { 1328f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com return; 1329f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com } 1330c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkPixmap& pmap = unlocker.pixmap(); 1331e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(matrix.getTranslateX()); 1332e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(matrix.getTranslateY()); 1333c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (clipHandlesSprite(*fRC, ix, iy, pmap)) { 133457bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby char storage[kSkBlitterContextSize]; 133557bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby SkArenaAlloc allocator{storage}; 1336a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 1337f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, *paint, pmap, ix, iy, &allocator); 1338045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (blitter) { 1339c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkScan::FillIRect(SkIRect::MakeXYWH(ix, iy, pmap.width(), pmap.height()), 1340c240e719b2bebd3711ade4e6fe056921aa7b0521reed *fRC, blitter); 1341045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1343c240e719b2bebd3711ade4e6fe056921aa7b0521reed // if !blitter, then we fall-through to the slower case 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1346a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now make a temp draw on the stack, and use it 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 1351a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 135270ac8a9d091d385bf5244125159c4d8509a0c470Matt Sarett if (bitmap.colorType() == kAlpha_8_SkColorType && !paint->getColorFilter()) { 1353f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita draw.drawBitmapAsMask(bitmap, *paint); 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1355f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita SkAutoBitmapShaderInstall install(bitmap, *paint); 13560393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkPaint& paintWithShader = install.paintWithShader(); 13570393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height()); 13580393912de72bc3d8b3640c122c53470dd0da1e6dreed if (dstBounds) { 13590393912de72bc3d8b3640c122c53470dd0da1e6dreed this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds); 13600393912de72bc3d8b3640c122c53470dd0da1e6dreed } else { 13610393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.drawRect(srcBounds, paintWithShader); 13620393912de72bc3d8b3640c122c53470dd0da1e6dreed } 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1366c240e719b2bebd3711ade4e6fe056921aa7b0521reedvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& origPaint) const { 1367f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 1368a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1370045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1372900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1376c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkIRect bounds = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1378045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->quickReject(bounds)) { 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // nothing to draw 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 138240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint paint(origPaint); 138340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com paint.setStyle(SkPaint::kFill_Style); 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1385c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkAutoPixmapUnlock unlocker; 1386c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (!bitmap.requestLock(&unlocker)) { 1387c240e719b2bebd3711ade4e6fe056921aa7b0521reed return; 1388c240e719b2bebd3711ade4e6fe056921aa7b0521reed } 1389c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkPixmap& pmap = unlocker.pixmap(); 1390c240e719b2bebd3711ade4e6fe056921aa7b0521reed 139196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, pmap)) { 1392a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 139357bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby char storage[kSkBlitterContextSize]; 139457bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby SkArenaAlloc allocator{storage}; 139541e010cb901c0da9066c4df562030808c9ccd7f8reed SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, paint, pmap, x, y, &allocator); 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 1397045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(bounds, *fRC, blitter); 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get a scalar version of our rect 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(bounds); 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14089c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org // create shader with offset 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(r.fLeft, r.fTop); 14109c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoBitmapShaderInstall install(bitmap, paint, &matrix); 14119c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org const SkPaint& shaderPaint = install.paintWithShader(); 1412a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call ourself with a rect 1417a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com // is this OK if paint has a rasterizer? 141840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com draw.drawRect(r, shaderPaint); 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h" 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h" 1425e69137620ab0b5b40d230318c8e11b822f63cb9dreed@google.com#include "SkTextToPathIter.h" 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14288128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.orgbool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { 14298128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // hairline glyphs are fast enough so we don't need to cache them 14308128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 14318128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 14328128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 14338128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14348128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // we don't cache perspective 14358128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (ctm.hasPerspective()) { 14368128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 14378128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 14388128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14398128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org SkMatrix textM; 14408128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); 14418128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org} 14428128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 1446f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1448166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com SkTextToPathIter iter(text, byteLength, paint, true); 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setScale(iter.getPathScale(), iter.getPathScale()); 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(x, y); 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos, prevXPos = 0; 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14577b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com while (iter.next(&iterPath, &xpos)) { 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(xpos - prevXPos, 0); 14597b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (iterPath) { 14607b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com const SkPaint& pnt = iter.getPaint(); 14617b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (fDevice) { 14627b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com fDevice->drawPath(*this, *iterPath, pnt, &matrix, false); 14637b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } else { 14647b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com this->drawPath(*iterPath, pnt, &matrix, false); 14657b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } 1466f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevXPos = xpos; 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// disable warning : local variable used without having been initialized 1472d7dc76f7e99309cbd09a5420c22e55b951067debbungeman#if defined _WIN32 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1477f553e4e09cd2baf15fc041daab8a08bd46e352f0herb//////////////////////////////////////////////////////////////////////////////////////////////////// 14782e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1479d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbclass DrawOneGlyph { 1480d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbpublic: 1481d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter) 1482d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb : fUseRegionToDraw(UsingRegionToDraw(draw.fRC)) 1483d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fGlyphCache(cache) 1484d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fBlitter(blitter) 1485d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr) 1486d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fDraw(draw) 1487d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fPaint(paint) 1488d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fClipBounds(PickClipBounds(draw)) { } 1489d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 1490d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 1491d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb position += rounding; 1492d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // Prevent glyphs from being drawn outside of or straddling the edge of device space. 1493875e13ca0990e32da9db639743a913efe77f7e89mtklein // Comparisons written a little weirdly so that NaN coordinates are treated safely. 1494875e13ca0990e32da9db639743a913efe77f7e89mtklein auto gt = [](float a, int b) { return !(a <= (float)b); }; 1495875e13ca0990e32da9db639743a913efe77f7e89mtklein auto lt = [](float a, int b) { return !(a >= (float)b); }; 1496875e13ca0990e32da9db639743a913efe77f7e89mtklein if (gt(position.fX, INT_MAX - (INT16_MAX + UINT16_MAX)) || 1497875e13ca0990e32da9db639743a913efe77f7e89mtklein lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) || 1498875e13ca0990e32da9db639743a913efe77f7e89mtklein gt(position.fY, INT_MAX - (INT16_MAX + UINT16_MAX)) || 1499875e13ca0990e32da9db639743a913efe77f7e89mtklein lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))) { 1500d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return; 1501d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1502d095f2bf06ca810844233bea9fb06de585643b32bungeman 150377a9cc1dead147fc547895d3725d9ee2150cda73benjaminwagner int left = SkScalarFloorToInt(position.fX); 150477a9cc1dead147fc547895d3725d9ee2150cda73benjaminwagner int top = SkScalarFloorToInt(position.fY); 1505d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1507d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb left += glyph.fLeft; 1508d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb top += glyph.fTop; 15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1510d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb int right = left + glyph.fWidth; 1511d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb int bottom = top + glyph.fHeight; 15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1513d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkMask mask; 1514d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask.fBounds.set(left, top, right, bottom); 1515875e13ca0990e32da9db639743a913efe77f7e89mtklein SkASSERT(!mask.fBounds.isEmpty()); 151683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 1517d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (fUseRegionToDraw) { 1518d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkRegion::Cliperator clipper(*fClip, mask.fBounds); 151983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 1520d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (!clipper.done() && this->getImageData(glyph, &mask)) { 1521d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkIRect& cr = clipper.rect(); 1522d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb do { 1523d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb this->blitMask(mask, cr); 1524d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb clipper.next(); 1525d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } while (!clipper.done()); 1526d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1527d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } else { 1528d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkIRect storage; 1529d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkIRect* bounds = &mask.fBounds; 1530d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 1531d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // this extra test is worth it, assuming that most of the time it succeeds 1532d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // since we can avoid writing to storage 1533d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) { 1534d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds)) 1535d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return; 1536d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb bounds = &storage; 1537d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 153883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 1539d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (this->getImageData(glyph, &mask)) { 1540d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb this->blitMask(mask, *bounds); 1541d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1542cd7f03597475ea423aa819bdae03996b26874dd5herb } 154383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 15448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1545d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbprivate: 1546d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb static bool UsingRegionToDraw(const SkRasterClip* rClip) { 1547d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return rClip->isBW() && !rClip->isRect(); 1548d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 15492e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1550d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb static SkIRect PickClipBounds(const SkDraw& draw) { 1551d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkRasterClip& rasterClip = *draw.fRC; 15522e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1553d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (rasterClip.isBW()) { 1554d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return rasterClip.bwRgn().getBounds(); 1555d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } else { 1556d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return rasterClip.aaRgn().getBounds(); 1557001e74426672e00f3f2783ccf728031662d4a358herb } 15589447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 1559001e74426672e00f3f2783ccf728031662d4a358herb 1560d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb bool getImageData(const SkGlyph& glyph, SkMask* mask) { 1561d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph)); 1562d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (nullptr == bits) { 1563d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return false; // can't rasterize glyph 1564d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1565d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask->fImage = bits; 1566d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask->fRowBytes = glyph.rowBytes(); 1567d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1568d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return true; 15692e8fec79658baef06f4a9fca5e91a4e116b47b3dherb } 15702e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1571d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb void blitMask(const SkMask& mask, const SkIRect& clip) const { 1572d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (SkMask::kARGB32_Format == mask.fFormat) { 1573d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkBitmap bm; 1574d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb bm.installPixels( 1575d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), 1576d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb (SkPMColor*)mask.fImage, mask.fRowBytes); 1577d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 1578d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint); 1579045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1580d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb fBlitter->blitMask(mask, clip); 1581045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15835bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 1584d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const bool fUseRegionToDraw; 1585d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkGlyphCache * const fGlyphCache; 1586d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkBlitter * const fBlitter; 1587d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkRegion* const fClip; 1588d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkDraw& fDraw; 1589d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkPaint& fPaint; 1590d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkIRect fClipBounds; 1591d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb}; 15922e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1593d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb//////////////////////////////////////////////////////////////////////////////////////////////////// 15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1595a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosmanuint32_t SkDraw::scalerContextFlags() const { 1596a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman uint32_t flags = SkPaint::kBoostContrast_ScalerContextFlag; 15977039f74a8b1d39b9c44fd357912ce66e6bc9fd25Brian Osman if (!fDevice->imageInfo().colorSpace()) { 1598a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman flags |= SkPaint::kFakeGamma_ScalerContextFlag; 1599a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman } 1600a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman return flags; 1601f6d1e605317917146362706ed460b5ed6624fcc5bungeman} 1602f6d1e605317917146362706ed460b5ed6624fcc5bungeman 16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText(const char text[], size_t byteLength, 16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) const { 160596fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(byteLength == 0 || text != nullptr); 16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1607f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 161096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 16118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 161436d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // SkScalarRec doesn't currently have a way of representing hairline stroke and 161536d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // will fill if its frame-width is 0. 1616ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 16178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawText_asPaths(text, byteLength, x, y, paint); 16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1621a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman SkAutoGlyphCache cache(paint, &fDevice->surfaceProps(), this->scalerContextFlags(), fMatrix); 162211a7f7f5998cb3d5605741e37a7f12f7477d480cherb 162311a7f7f5998cb3d5605741e37a7f12f7477d480cherb // The Blitter Choose needs to be live while using the blitter below. 162411a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 162511a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1626f6d1e605317917146362706ed460b5ed6624fcc5bungeman DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter()); 16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1628e59124ed1a62f1fec79679c38cabed622a756f75herb SkFindAndPlaceGlyph::ProcessText( 16294c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb paint.getTextEncoding(), text, byteLength, 1630f6d1e605317917146362706ed460b5ed6624fcc5bungeman {x, y}, *fMatrix, paint.getTextAlign(), cache.get(), drawOneGlyph); 16318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1635ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comvoid SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 163605c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkScalar pos[], int scalarsPerPosition, 163705c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkPoint& offset, const SkPaint& origPaint) const { 1638ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com // setup our std paint, in hopes of getting hits in the cache 1639ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkPaint paint(origPaint); 1640ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkScalar matrixScale = paint.setupForAsPaths(); 1641ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 16425a64902ee92847f53dfc5b211da19d074179be64reed@google.com SkMatrix matrix; 16435a64902ee92847f53dfc5b211da19d074179be64reed@google.com matrix.setScale(matrixScale, matrixScale); 16448f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 16454e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 16464e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setStyle(SkPaint::kFill_Style); 164796fcdcc219d2a0d3579719b84b28bede76efba64halcanary paint.setPathEffect(nullptr); 16484e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org 1649e34f17d23699abfc672289f51319b37294b3c257robertphillips SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(), 1650e34f17d23699abfc672289f51319b37294b3c257robertphillips paint.isDevKernText(), 1651e34f17d23699abfc672289f51319b37294b3c257robertphillips true); 1652a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman SkAutoGlyphCache cache(paint, &fDevice->surfaceProps(), this->scalerContextFlags(), nullptr); 1653ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 1654ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const char* stop = text + byteLength; 165579738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkTextAlignProc alignProc(paint.getTextAlign()); 165605c4a4322e7d4f3417b7df33825bab8603d52051fmalita SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 16578f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 16584e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org // Now restore the original settings, so we "draw" with whatever style/stroking. 16594e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setStyle(origPaint.getStyle()); 1660693fdbd6b81a860657612e7604430dd55d6e721bMike Reed paint.setPathEffect(origPaint.refPathEffect()); 16614e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org 1662ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com while (text < stop) { 1663d936f63c35fb7dfb2b6c20802206adbfc3cc48d0benjaminwagner const SkGlyph& glyph = glyphCacheProc(cache.get(), &text); 1664ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (glyph.fWidth) { 1665ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkPath* path = cache->findPath(glyph); 1666ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (path) { 1667cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1668cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1669cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com SkPoint loc; 1670cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen alignProc(tmsLoc, glyph, &loc); 16718f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 1672cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransX] = loc.fX; 1673cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransY] = loc.fY; 16745a64902ee92847f53dfc5b211da19d074179be64reed@google.com if (fDevice) { 16755a64902ee92847f53dfc5b211da19d074179be64reed@google.com fDevice->drawPath(*this, *path, paint, &matrix, false); 16765a64902ee92847f53dfc5b211da19d074179be64reed@google.com } else { 16775a64902ee92847f53dfc5b211da19d074179be64reed@google.com this->drawPath(*path, paint, &matrix, false); 16785a64902ee92847f53dfc5b211da19d074179be64reed@google.com } 1679ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1680ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1681ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com pos += scalarsPerPosition; 1682ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1683ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com} 1684ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPosText(const char text[], size_t byteLength, 168605c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkScalar pos[], int scalarsPerPosition, 168705c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkPoint& offset, const SkPaint& paint) const { 168896fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(byteLength == 0 || text != nullptr); 16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1691f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 169496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1698ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 169905c4a4322e7d4f3417b7df33825bab8603d52051fmalita this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint); 17008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1703a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman SkAutoGlyphCache cache(paint, &fDevice->surfaceProps(), this->scalerContextFlags(), fMatrix); 1704d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 17059be5ff6f9871ef22740094e7c25dd67329a73d20herb // The Blitter Choose needs to be live while using the blitter below. 170611a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 170711a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1708f6d1e605317917146362706ed460b5ed6624fcc5bungeman DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter()); 1709d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkPaint::Align textAlignment = paint.getTextAlign(); 17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17119be5ff6f9871ef22740094e7c25dd67329a73d20herb SkFindAndPlaceGlyph::ProcessPosText( 17124c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb paint.getTextEncoding(), text, byteLength, 1713f6d1e605317917146362706ed460b5ed6624fcc5bungeman offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache.get(), drawOneGlyph); 17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1716d7dc76f7e99309cbd09a5420c22e55b951067debbungeman#if defined _WIN32 17178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17225dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreedstatic SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 17278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint texs[], SkMatrix* matrix) { 17288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src[3], dst[3]; 1729a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[0] = texs[state.f0]; 17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[1] = texs[state.f1]; 17328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[2] = texs[state.f2]; 17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[0] = verts[state.f0]; 17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[1] = verts[state.f1]; 17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[2] = verts[state.f2]; 17368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return matrix->setPolyToPoly(src, dst, 3); 17378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkTriColorShader : public SkShader { 17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 174188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic SkTriColorShader(); 17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 174387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org class TriColorShaderContext : public SkShader::Context { 174487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org public: 1745e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&); 174687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual ~TriColorShaderContext(); 174736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void shadeSpan(int x, int y, SkPMColor dstC[], int count) override; 174887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 174987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org private: 175088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 175188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 175287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkMatrix fDstToUnit; 175387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor fColors[3]; 175488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic bool fSetup; 175587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 175687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org typedef SkShader::Context INHERITED; 175787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org }; 1758a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 175988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic struct TriColorShaderData { 176088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic const SkPoint* pts; 176188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic const SkColor* colors; 176288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic const VertState *state; 176388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic }; 176488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 17650f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 17667e44bb191633e225fd0455c267dbf67f9ee8633emtklein 17677e44bb191633e225fd0455c267dbf67f9ee8633emtklein // For serialization. This will never be called. 176896fcdcc219d2a0d3579719b84b28bede76efba64halcanary Factory getFactory() const override { sk_throw(); return nullptr; } 1769ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com 177088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // Supply setup data to context from drawing setup 177188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic void bindSetupData(TriColorShaderData* setupData) { fSetupData = setupData; } 177288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 177388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // Take the setup data from context when needed. 177488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData* takeSetupData() { 177588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData *data = fSetupData; 177688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic fSetupData = NULL; 177788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic return data; 177888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic } 177988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 178183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override { 178283e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby return alloc->make<TriColorShaderContext>(*this, rec); 1783ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 1784ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 178688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData *fSetupData; 178788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShader INHERITED; 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 179187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgbool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], 179287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int index0, int index1, int index2) { 1793a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[0] = SkPreMultiplyColor(colors[index0]); 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[1] = SkPreMultiplyColor(colors[index1]); 17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[2] = SkPreMultiplyColor(colors[index2]); 1797a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m, im; 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.reset(); 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(0, pts[index1].fX - pts[index0].fX); 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(1, pts[index2].fX - pts[index0].fX); 18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(2, pts[index0].fX); 18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(3, pts[index1].fY - pts[index0].fY); 18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(4, pts[index2].fY - pts[index0].fY); 18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(5, pts[index0].fY); 18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!m.invert(&im)) { 18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 180980116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix 181080116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org // as our interators are intrinsically tied to the vertices, and nothing else. 181180116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org SkMatrix ctmInv; 181280116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org if (!this->getCTM().invert(&ctmInv)) { 181380116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org return false; 181480116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org } 181588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // TODO replace INV(m) * INV(ctm) with INV(ctm * m) 181680116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org fDstToUnit.setConcat(im, ctmInv); 181792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return true; 18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 1821689411a87ca7d19abe04b5c9baff26bd96b2123ereed@android.com#include "SkComposeShader.h" 18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int ScalarTo256(SkScalar v) { 182443437c2f1928073a30c2bab6d32df854658235ecbenjaminwagner return static_cast<int>(SkScalarPin(v, 0, 1) * 256 + 0.5); 18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 182788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovicSkTriColorShader::SkTriColorShader() 182888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic : INHERITED(NULL) 182988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic , fSetupData(NULL) {} 183087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 1831e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader, 1832e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const ContextRec& rec) 183388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic : INHERITED(shader, rec) 183488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic , fSetup(false) {} 183587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 183687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} 183787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 183887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 183988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic SkTriColorShader* parent = static_cast<SkTriColorShader*>(const_cast<SkShader*>(&fShader)); 184088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData* set = parent->takeSetupData(); 184188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic if (set) { 184288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic fSetup = setup(set->pts, set->colors, set->state->f0, set->state->f1, set->state->f2); 184388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic } 184488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 184588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic if (!fSetup) { 184688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // Invalid matrices. Not checked before so no need to assert. 184788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic return; 184888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic } 184988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 185006a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org const int alphaScale = Sk255To256(this->getPaintAlpha()); 185106a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src; 1853a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += 1; 1857a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale1 = ScalarTo256(src.fX); 18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale2 = ScalarTo256(src.fY); 18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale0 = 256 - scale1 - scale2; 18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale0 < 0) { 18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale1 > scale2) { 18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale2 = 256 - scale1; 18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale1 = 256 - scale2; 18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale0 = 0; 18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1869a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 187006a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org if (256 != alphaScale) { 187106a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale0 = SkAlphaMul(scale0, alphaScale); 187206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale1 = SkAlphaMul(scale1, alphaScale); 187306a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale2 = SkAlphaMul(scale2, alphaScale); 187406a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org } 187506a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 187706a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[1], scale1) + 187806a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[2], scale2); 18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18820f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 188376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTriColorShader::toString(SkString* str) const { 188476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkTriColorShader: ("); 188576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 188676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 188776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 188876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 188976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 189076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 189176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint vertices[], const SkPoint textures[], 18947d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed const SkColor colors[], SkBlendMode bmode, 18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 189749f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(0 == count || vertices); 1898a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // abort early if there is nothing to draw 1900045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 19018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1903a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform out vertices into device coordinates 19058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSTMalloc<16, SkPoint> storage(count); 19068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* devVerts = storage.get(); 19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapPoints(devVerts, vertices, count); 1908a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 19108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com We can draw the vertices in 1 of 4 ways: 19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - solid color (no shader/texture[], no colors[]) 19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just colors (no shader/texture[], has colors[]) 19148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just texture (has shader/texture[], no colors[]) 19158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - colors * texture (has shader/texture[], has colors[]) 1916a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Thus for texture drawing, we need both texture[] and a shader. 19188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 19198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19208a21c9fe7f5fef9e87115defef27bd7218419f28reed auto triShader = sk_make_sp<SkTriColorShader>(); 19218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = p.getShader(); 192496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == shader) { 19258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no shader, we ignore the texture coordinates 192696fcdcc219d2a0d3579719b84b28bede76efba64halcanary textures = nullptr; 192796fcdcc219d2a0d3579719b84b28bede76efba64halcanary } else if (nullptr == textures) { 19288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we don't have texture coordinates, ignore the shader 192996fcdcc219d2a0d3579719b84b28bede76efba64halcanary p.setShader(nullptr); 193096fcdcc219d2a0d3579719b84b28bede76efba64halcanary shader = nullptr; 19318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup the custom shader (if needed) 193449f085dddff10473b6ebf832a974288300224e60bsalomon if (colors) { 193596fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == textures) { 19368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // just colors (no texture) 19378a21c9fe7f5fef9e87115defef27bd7218419f28reed p.setShader(triShader); 19388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 19398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // colors * texture 19408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(shader); 19417d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed p.setShader(SkShader::MakeComposeShader(triShader, sk_ref_sp(shader), bmode)); 19428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 194541e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, p); 194687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Abort early if we failed to create a shader context. 1947ea033606a06d05d2d42aa7118409fee798e53167reed@google.com if (blitter->isNullBlitter()) { 1948ea033606a06d05d2d42aa7118409fee798e53167reed@google.com return; 1949ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 1950ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup our state and function pointer for iterating triangles 19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState state(count, indices, indexCount); 19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState::Proc vertProc = state.chooseProc(vmode); 1954a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 195549f085dddff10473b6ebf832a974288300224e60bsalomon if (textures || colors) { 195688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic SkTriColorShader::TriColorShaderData verticesSetup = { vertices, colors, &state }; 195788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 195900dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita auto* blitterPtr = blitter.get(); 196000dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 196100dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita SkTLazy<SkLocalMatrixShader> localShader; 196200dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita SkTLazy<SkAutoBlitterChoose> localBlitter; 196300dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 196449f085dddff10473b6ebf832a974288300224e60bsalomon if (textures) { 196580116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org SkMatrix tempM; 19668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (texture_to_matrix(state, vertices, textures, &tempM)) { 196700dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita localShader.init(p.refShader(), tempM); 196800dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 196900dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita SkPaint localPaint(p); 197000dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita localPaint.setShader(sk_ref_sp(localShader.get())); 197100dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 197200dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita blitterPtr = localBlitter.init(fDst, *fMatrix, localPaint)->get(); 197300dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita if (blitterPtr->isNullBlitter()) { 19748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 19758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 197849f085dddff10473b6ebf832a974288300224e60bsalomon if (colors) { 19798a21c9fe7f5fef9e87115defef27bd7218419f28reed triShader->bindSetupData(&verticesSetup); 19808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1981045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1982045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPoint tmp[] = { 1983045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 1984045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com }; 198500dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita SkScan::FillTriangle(tmp, *fRC, blitterPtr); 198600dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita triShader->bindSetupData(nullptr); 19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1989559a8833f0eae4af37dc0ffc3ee97e1fb14817b1commit-bot@chromium.org // no colors[] and no texture, stroke hairlines with paint's color. 19905dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias()); 1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& clip = *fRC; 19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 19935dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkPoint array[] = { 19945dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0] 19955dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed }; 19965dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed hairProc(array, 4, clip, blitter.get()); 19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20010a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 20020a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2006f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkDraw::validate() const { 200796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(fMatrix != nullptr); 200896fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(fRC != nullptr); 20098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2010045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& cr = fRC->getBounds(); 20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect br; 20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 201341e010cb901c0da9066c4df562030808c9ccd7f8reed br.set(0, 0, fDst.width(), fDst.height()); 20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cr.isEmpty() || br.contains(cr)); 20158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 20188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////// 20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 20228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 20238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h" 20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 2027b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkMaskFilter* filter, const SkMatrix* filterMatrix, 20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect* bounds) { 20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (devPath.isEmpty()) { 20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // init our bounds from the path 203411fa2247b747eb75e2f158dc7571d458ed6c0115reed *bounds = devPath.getBounds().makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut(); 2035a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20366db75fc2c393ba86a3f533597a8bcd348477e79ctomhudson@google.com SkIPoint margin = SkIPoint::Make(0, 0); 20378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (filter) { 20388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filterMatrix); 2039a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20405af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkMask srcM, dstM; 2041a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fBounds = *bounds; 20438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fFormat = SkMask::kA8_Format; 20448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 20468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2048a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20495af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com // (possibly) trim the bounds to reflect the clip 20508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (plus whatever slop the filter needs) 20515af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (clipBounds) { 20523555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // Ugh. Guard against gigantic margins from wacky filters. Without this 20533555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // check we can request arbitrary amounts of slop beyond our visible 20543555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // clip, and bring down the renderer (at least on finite RAM machines 20553555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // like handsets, etc.). Need to balance this invented value between 20563555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // quality of large filters like blurs, and the corresponding memory 20573555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // requests. 20583555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com static const int MAX_MARGIN = 128; 205911fa2247b747eb75e2f158dc7571d458ed6c0115reed if (!bounds->intersect(clipBounds->makeOutset(SkMin32(margin.fX, MAX_MARGIN), 206011fa2247b747eb75e2f158dc7571d458ed6c0115reed SkMin32(margin.fY, MAX_MARGIN)))) { 20615af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com return false; 20625af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 20668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2068055e192adc0072ae2548ef5431ceee652945f9c2bsalomonstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath, 2069055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkStrokeRec::InitStyle style) { 207041e010cb901c0da9066c4df562030808c9ccd7f8reed SkDraw draw; 207141e010cb901c0da9066c4df562030808c9ccd7f8reed if (!draw.fDst.reset(mask)) { 207241e010cb901c0da9066c4df562030808c9ccd7f8reed return; 207341e010cb901c0da9066c4df562030808c9ccd7f8reed } 207441e010cb901c0da9066c4df562030808c9ccd7f8reed 2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip; 2076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMatrix matrix; 2077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPaint paint; 20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2079045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 20828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2083045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com draw.fRC = &clip; 20848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setAntiAlias(true); 2086055e192adc0072ae2548ef5431ceee652945f9c2bsalomon switch (style) { 2087055e192adc0072ae2548ef5431ceee652945f9c2bsalomon case SkStrokeRec::kHairline_InitStyle: 2088055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkASSERT(!paint.getStrokeWidth()); 2089055e192adc0072ae2548ef5431ceee652945f9c2bsalomon paint.setStyle(SkPaint::kStroke_Style); 2090055e192adc0072ae2548ef5431ceee652945f9c2bsalomon break; 2091055e192adc0072ae2548ef5431ceee652945f9c2bsalomon case SkStrokeRec::kFill_InitStyle: 2092055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkASSERT(paint.getStyle() == SkPaint::kFill_Style); 2093055e192adc0072ae2548ef5431ceee652945f9c2bsalomon break; 2094055e192adc0072ae2548ef5431ceee652945f9c2bsalomon 2095055e192adc0072ae2548ef5431ceee652945f9c2bsalomon } 20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawPath(devPath, paint); 20978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 210030711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMaskFilter* filter, const SkMatrix* filterMatrix, 21012ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkMask* mask, SkMask::CreateMode mode, 2102055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkStrokeRec::InitStyle style) { 21038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustRenderImage_CreateMode != mode) { 21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2107a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fFormat = SkMask::kA8_Format; 21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fRowBytes = mask->fBounds.width(); 2111543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask->computeImageSize(); 2112543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 2113543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // we're too big to allocate the mask, abort 2114543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; 2115543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 2116543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com mask->fImage = SkMask::AllocImage(size); 21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask->fImage, 0, mask->computeImageSize()); 21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustComputeBounds_CreateMode != mode) { 21212ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org draw_into_mask(*mask, devPath, style); 21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2123a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2126