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 */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 883e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby#include "SkArenaAlloc.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkComposeShader.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 12573f22b3bd295bb2e3b9e6ab41f5dfeb557897f9reed@google.com#include "SkColorShader.h" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 1576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#include "SkString.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 177d954ad797176afedb9262fdea4507d0fc60eb9dMike Reedsk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, 187d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode mode) { 197d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (!src || !dst) { 207d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return nullptr; 217d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed } 227d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (SkBlendMode::kSrc == mode) { 237d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return src; 247d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed } 257d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (SkBlendMode::kDst == mode) { 267d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return dst; 277d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed } 287d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode)); 297d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed} 307d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed 3182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 3282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoAlphaRestore { 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlpha = paint->getAlpha(); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = paint; 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint->setAlpha(newAlpha); 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 4182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com ~SkAutoAlphaRestore() { 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint->setAlpha(fAlpha); 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint* fPaint; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fAlpha; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 48e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5060c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkComposeShader::CreateProc(SkReadBuffer& buffer) { 518a21c9fe7f5fef9e87115defef27bd7218419f28reed sk_sp<SkShader> shaderA(buffer.readShader()); 528a21c9fe7f5fef9e87115defef27bd7218419f28reed sk_sp<SkShader> shaderB(buffer.readShader()); 537d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode mode; 547d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode2_Version)) { 557d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed sk_sp<SkXfermode> xfer = buffer.readXfermode(); 567d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed mode = xfer ? xfer->blend() : SkBlendMode::kSrcOver; 577d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed } else { 587d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed mode = (SkBlendMode)buffer.read32(); 597d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed } 608a21c9fe7f5fef9e87115defef27bd7218419f28reed if (!shaderA || !shaderB) { 6196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 637d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return sk_make_sp<SkComposeShader>(std::move(shaderA), std::move(shaderB), mode); 649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 668b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkComposeShader::flatten(SkWriteBuffer& buffer) const { 678a21c9fe7f5fef9e87115defef27bd7218419f28reed buffer.writeFlattenable(fShaderA.get()); 688a21c9fe7f5fef9e87115defef27bd7218419f28reed buffer.writeFlattenable(fShaderB.get()); 697d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed buffer.write32((int)fMode); 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7283e939bcb79790f5ae3b28c398fbcf034675a6e5Herb DerbySkShader::Context* SkComposeShader::onMakeContext( 7383e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby const ContextRec& rec, SkArenaAlloc* alloc) const 7483e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby{ 75e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org // we preconcat our localMatrix (if any) with the device matrix 76e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org // before calling our sub-shaders 77e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org SkMatrix tmpM; 78e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix()); 799a40803f2bc0ed14c30bdd2213945b01d9c4c977skia.committer@gmail.com 801ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org // Our sub-shaders need to see opaque, so by combining them we don't double-alphatize the 811ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org // result. ComposeShader itself will respect the alpha, and post-apply it after calling the 821ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org // sub-shaders. 831ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org SkPaint opaquePaint(*rec.fPaint); 841ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org opaquePaint.setAlpha(0xFF); 85edda70e020630103270c815b7499e8b02271875dskia.committer@gmail.com 86e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org ContextRec newRec(rec); 87e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org newRec.fMatrix = &tmpM; 881ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org newRec.fPaint = &opaquePaint; 89e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org 9083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby SkShader::Context* contextA = fShaderA->makeContext(newRec, alloc); 9183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby SkShader::Context* contextB = fShaderB->makeContext(newRec, alloc); 92ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org if (!contextA || !contextB) { 9396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 94ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 9587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 9683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby return alloc->make<ComposeShaderContext>(*this, rec, contextA, contextB); 97a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com} 98a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com 9987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkComposeShader::ComposeShaderContext::ComposeShaderContext( 100e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkComposeShader& shader, const ContextRec& rec, 10187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* contextA, SkShader::Context* contextB) 102e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) 10387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org , fShaderContextA(contextA) 10487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org , fShaderContextB(contextB) {} 10587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 106795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.orgbool SkComposeShader::asACompose(ComposeRec* rec) const { 107795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.org if (rec) { 108faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed rec->fShaderA = fShaderA.get(); 109faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed rec->fShaderB = fShaderB.get(); 1107d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed rec->fBlendMode = fMode; 111795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.org } 112795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.org return true; 113795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.org} 114795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.org 115795905562d1bd8bbedcf47f6a00efb220ec8bbe0commit-bot@chromium.org 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// larger is better (fewer times we have to loop), but we shouldn't 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// take up too much stack-space (each element is 4 bytes) 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define TMP_COLOR_COUNT 64 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { 12187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContextA = fShaderContextA; 12287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContextB = fShaderContextB; 1237d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode mode = static_cast<const SkComposeShader&>(fShader).fMode; 12487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned scale = SkAlpha255To256(this->getPaintAlpha()); 12582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor tmp[TMP_COLOR_COUNT]; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1287d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkXfermode* xfer = SkXfermode::Peek(mode); 1297d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (nullptr == xfer) { // implied SRC_OVER 130c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com // TODO: when we have a good test-case, should use SkBlitRow::Proc32 131c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com // for these loops 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n = count; 13482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (n > TMP_COLOR_COUNT) { 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = TMP_COLOR_COUNT; 13682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 13782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 13887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org shaderContextA->shadeSpan(x, y, result, n); 13987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org shaderContextB->shadeSpan(x, y, tmp, n); 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (256 == scale) { 14282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < n; i++) { 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result[i] = SkPMSrcOver(tmp[i], result[i]); 14482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 14582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 14682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < n; i++) { 14782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), 14882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com scale); 14982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result += n; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += n; 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count > 0); 15682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { // use mode for the composition 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n = count; 15982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (n > TMP_COLOR_COUNT) { 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = TMP_COLOR_COUNT; 16182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 16282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 16387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org shaderContextA->shadeSpan(x, y, result, n); 16487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org shaderContextB->shadeSpan(x, y, tmp, n); 1657d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed xfer->xfer32(result, tmp, n, nullptr); 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1671ab536f16164795782a75b11efcb17541cbc2e26commit-bot@chromium.org if (256 != scale) { 16882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < n; i++) { 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result[i] = SkAlphaMulQ(result[i], scale); 17082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result += n; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += n; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count > 0); 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 18073fa61670d95c52250a660a2cec618ab77716934wangyix#if SK_SUPPORT_GPU 18173fa61670d95c52250a660a2cec618ab77716934wangyix 182036fd8e6f66b53cf87a5f91083cae82f0aeb3635wangyix#include "effects/GrConstColorProcessor.h" 183809e5afdd95962465a51e3dbab707abf9d594fabwangyix#include "effects/GrXfermodeFragmentProcessor.h" 18473fa61670d95c52250a660a2cec618ab77716934wangyix 18573fa61670d95c52250a660a2cec618ab77716934wangyix///////////////////////////////////////////////////////////////////// 18673fa61670d95c52250a660a2cec618ab77716934wangyix 187839345d63466a4209a0985654ec033624821fd78brianosmansk_sp<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(const AsFPArgs& args) const { 1887d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed switch (fMode) { 1897d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kClear: 190618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(), 19106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman GrConstColorProcessor::kIgnore_InputMode); 19273fa61670d95c52250a660a2cec618ab77716934wangyix break; 1937d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kSrc: 194839345d63466a4209a0985654ec033624821fd78brianosman return fShaderB->asFragmentProcessor(args); 19573fa61670d95c52250a660a2cec618ab77716934wangyix break; 1967d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kDst: 197839345d63466a4209a0985654ec033624821fd78brianosman return fShaderA->asFragmentProcessor(args); 19873fa61670d95c52250a660a2cec618ab77716934wangyix break; 19973fa61670d95c52250a660a2cec618ab77716934wangyix default: 200839345d63466a4209a0985654ec033624821fd78brianosman sk_sp<GrFragmentProcessor> fpA(fShaderA->asFragmentProcessor(args)); 20106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman if (!fpA) { 20273fa61670d95c52250a660a2cec618ab77716934wangyix return nullptr; 20373fa61670d95c52250a660a2cec618ab77716934wangyix } 204839345d63466a4209a0985654ec033624821fd78brianosman sk_sp<GrFragmentProcessor> fpB(fShaderB->asFragmentProcessor(args)); 20506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman if (!fpB) { 20673fa61670d95c52250a660a2cec618ab77716934wangyix return nullptr; 20773fa61670d95c52250a660a2cec618ab77716934wangyix } 20806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), 2097d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed std::move(fpA), fMode); 21073fa61670d95c52250a660a2cec618ab77716934wangyix } 21173fa61670d95c52250a660a2cec618ab77716934wangyix} 21273fa61670d95c52250a660a2cec618ab77716934wangyix#endif 21373fa61670d95c52250a660a2cec618ab77716934wangyix 2140f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 21576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkComposeShader::toString(SkString* str) const { 21676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkComposeShader: ("); 21776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 21876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("ShaderA: "); 21976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com fShaderA->toString(str); 22076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(" ShaderB: "); 22176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com fShaderB->toString(str); 2227d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (SkBlendMode::kSrcOver != fMode) { 2237d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed str->appendf(" Xfermode: %s", SkXfermode::ModeName(fMode)); 2248464a960b83e3577bfa419693b3b27dfad82c8c8halcanary } 22576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 22676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 22776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 22876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 22976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 23076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 231