1b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com/* 2b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * Copyright 2013 Google Inc. 3b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * 4b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 5b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * found in the LICENSE file. 6b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com */ 7b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com 8e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#include "SkArithmeticMode.h" 9e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#include "SkColorPriv.h" 108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 12b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#include "SkString.h" 13e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#include "SkUnPreMultiply.h" 149a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU 1516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "SkArithmeticMode_gpu.h" 169a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif 17e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 18e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgclass SkArithmeticMode_scalar : public SkXfermode { 19e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgpublic: 208781123a177fbb9f933254da4cee0a983522b33breed SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, 218781123a177fbb9f933254da4cee0a983522b33breed bool enforcePMColor) { 228781123a177fbb9f933254da4cee0a983522b33breed fK[0] = k1; 238781123a177fbb9f933254da4cee0a983522b33breed fK[1] = k2; 248781123a177fbb9f933254da4cee0a983522b33breed fK[2] = k3; 258781123a177fbb9f933254da4cee0a983522b33breed fK[3] = k4; 268781123a177fbb9f933254da4cee0a983522b33breed fEnforcePMColor = enforcePMColor; 27e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 288781123a177fbb9f933254da4cee0a983522b33breed 298781123a177fbb9f933254da4cee0a983522b33breed void xfer32(SkPMColor[], const SkPMColor[], int count, const SkAlpha[]) const override; 30e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 310f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 329a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar) 339a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org 349a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU 354f0379444db31421894d2fce7c85889fe5eaa01arobertphillips const GrFragmentProcessor* getFragmentProcessorForImageFilter( 364f0379444db31421894d2fce7c85889fe5eaa01arobertphillips const GrFragmentProcessor* dst) const override; 374f0379444db31421894d2fce7c85889fe5eaa01arobertphillips GrXPFactory* asXPFactory() const override; 389a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif 39e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 40e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgprivate: 4136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void flatten(SkWriteBuffer& buffer) const override { 429a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org buffer.writeScalar(fK[0]); 439a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org buffer.writeScalar(fK[1]); 449a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org buffer.writeScalar(fK[2]); 459a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org buffer.writeScalar(fK[3]); 4651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org buffer.writeBool(fEnforcePMColor); 479a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org } 4827a6e86fb17fce7ce962b9080eae36926e87d568halcanary 49e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalar fK[4]; 5051a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org bool fEnforcePMColor; 51b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com 529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed friend class SkArithmeticMode; 539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 5498ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com typedef SkXfermode INHERITED; 55e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}; 56e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) { 589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar k1 = buffer.readScalar(); 599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar k2 = buffer.readScalar(); 609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar k3 = buffer.readScalar(); 619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar k4 = buffer.readScalar(); 629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const bool enforcePMColor = buffer.readBool(); 638781123a177fbb9f933254da4cee0a983522b33breed return SkArithmeticMode::Create(k1, k2, k3, k4, enforcePMColor); 649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 66e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int pinToByte(int value) { 67e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org if (value < 0) { 68e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org value = 0; 69e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } else if (value > 255) { 70e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org value = 255; 71e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 72e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org return value; 73e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org} 74e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 75e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, 76e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org int src, int dst) { 77e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalar result = SkScalarMul(k1, src * dst) + 78e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalarMul(k2, src) + 79e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalarMul(k3, dst) + 80e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org k4; 81e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org int res = SkScalarRoundToInt(result); 82e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org return pinToByte(res); 83e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org} 84e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 85e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int blend(int src, int dst, int scale) { 86e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org return dst + ((src - dst) * scale >> 8); 87e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org} 88e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 89e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgvoid SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[], 9030da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com int count, const SkAlpha aaCoverage[]) const { 91e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalar k1 = fK[0] / 255; 92e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalar k2 = fK[1]; 93e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalar k3 = fK[2]; 94e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkScalar k4 = fK[3] * 255; 95e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 96e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org for (int i = 0; i < count; ++i) { 9796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if ((nullptr == aaCoverage) || aaCoverage[i]) { 98e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkPMColor sc = src[i]; 99e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org SkPMColor dc = dst[i]; 100e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 101e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org int a, r, g, b; 102e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 1038781123a177fbb9f933254da4cee0a983522b33breed a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc)); 1048781123a177fbb9f933254da4cee0a983522b33breed r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc)); 1058781123a177fbb9f933254da4cee0a983522b33breed g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc)); 1068781123a177fbb9f933254da4cee0a983522b33breed b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc)); 1078781123a177fbb9f933254da4cee0a983522b33breed if (fEnforcePMColor) { 1088781123a177fbb9f933254da4cee0a983522b33breed r = SkMin32(r, a); 1098781123a177fbb9f933254da4cee0a983522b33breed g = SkMin32(g, a); 1108781123a177fbb9f933254da4cee0a983522b33breed b = SkMin32(b, a); 111e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 112e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 113e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org // apply antialias coverage if necessary 114e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org if (aaCoverage && 0xFF != aaCoverage[i]) { 115e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org int scale = aaCoverage[i] + (aaCoverage[i] >> 7); 116e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org a = blend(a, SkGetPackedA32(sc), scale); 117e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org r = blend(r, SkGetPackedR32(sc), scale); 118e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org g = blend(g, SkGetPackedG32(sc), scale); 119e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org b = blend(b, SkGetPackedB32(sc), scale); 120e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 121e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 12251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b); 123e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 124e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 125e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org} 126e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 1270f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 128b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkArithmeticMode_scalar::toString(SkString* str) const { 129b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com str->append("SkArithmeticMode_scalar: "); 130b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com for (int i = 0; i < 4; ++i) { 131b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com str->appendScalar(fK[i]); 13251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org str->append(" "); 133b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com } 13451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org str->appendS32(fEnforcePMColor ? 1 : 0); 135b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com} 136b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif 137e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 138e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 139e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org 140e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgSkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2, 14151a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org SkScalar k3, SkScalar k4, 14251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org bool enforcePMColor) { 1438781123a177fbb9f933254da4cee0a983522b33breed if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) && 1448781123a177fbb9f933254da4cee0a983522b33breed SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { 1458781123a177fbb9f933254da4cee0a983522b33breed return SkXfermode::Create(SkXfermode::kSrc_Mode); 1468781123a177fbb9f933254da4cee0a983522b33breed } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && 1478781123a177fbb9f933254da4cee0a983522b33breed SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) { 1488781123a177fbb9f933254da4cee0a983522b33breed return SkXfermode::Create(SkXfermode::kDst_Mode); 149e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org } 1508781123a177fbb9f933254da4cee0a983522b33breed 1518781123a177fbb9f933254da4cee0a983522b33breed return new SkArithmeticMode_scalar(k1, k2, k3, k4, enforcePMColor); 152e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org} 1539a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org 1549a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org 1559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org////////////////////////////////////////////////////////////////////////////// 1569a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org 1579a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU 1584f0379444db31421894d2fce7c85889fe5eaa01arobertphillipsconst GrFragmentProcessor* SkArithmeticMode_scalar::getFragmentProcessorForImageFilter( 1594f0379444db31421894d2fce7c85889fe5eaa01arobertphillips const GrFragmentProcessor* dst) const { 1604f0379444db31421894d2fce7c85889fe5eaa01arobertphillips return GrArithmeticFP::Create(SkScalarToFloat(fK[0]), 1614f0379444db31421894d2fce7c85889fe5eaa01arobertphillips SkScalarToFloat(fK[1]), 1624f0379444db31421894d2fce7c85889fe5eaa01arobertphillips SkScalarToFloat(fK[2]), 1634f0379444db31421894d2fce7c85889fe5eaa01arobertphillips SkScalarToFloat(fK[3]), 1644f0379444db31421894d2fce7c85889fe5eaa01arobertphillips fEnforcePMColor, 1654f0379444db31421894d2fce7c85889fe5eaa01arobertphillips dst); 1669a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org} 1679a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org 1684f0379444db31421894d2fce7c85889fe5eaa01arobertphillipsGrXPFactory* SkArithmeticMode_scalar::asXPFactory() const { 1694f0379444db31421894d2fce7c85889fe5eaa01arobertphillips return GrArithmeticXPFactory::Create(SkScalarToFloat(fK[0]), 1704f0379444db31421894d2fce7c85889fe5eaa01arobertphillips SkScalarToFloat(fK[1]), 1714f0379444db31421894d2fce7c85889fe5eaa01arobertphillips SkScalarToFloat(fK[2]), 1724f0379444db31421894d2fce7c85889fe5eaa01arobertphillips SkScalarToFloat(fK[3]), 1734f0379444db31421894d2fce7c85889fe5eaa01arobertphillips fEnforcePMColor); 174f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel} 175f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel 1769a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif 1779a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org 1789a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode) 1799a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar) 1809a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 181