1b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com/* 2b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com * Copyright 2013 Google Inc. 3b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com * 4b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com * Use of this source code is governed by a BSD-style license that can be 5b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com * found in the LICENSE file. 6b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com */ 7b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 8b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com#include "SkLerpXfermode.h" 9b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com#include "SkColorPriv.h" 108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 12b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com#include "SkString.h" 13b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 14b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comSkXfermode* SkLerpXfermode::Create(SkScalar scale) { 15b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com int scale256 = SkScalarRoundToInt(scale * 256); 16b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (scale256 >= 256) { 17b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com return SkXfermode::Create(SkXfermode::kSrc_Mode); 18b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } else if (scale256 <= 0) { 19b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com return SkXfermode::Create(SkXfermode::kDst_Mode); 20b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 21b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com return SkNEW_ARGS(SkLerpXfermode, (scale256)); 22b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 23b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 24b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comSkLerpXfermode::SkLerpXfermode(unsigned scale256) : fScale256(scale256) {} 25b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 268b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkLerpXfermode::SkLerpXfermode(SkReadBuffer& buffer) 27b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com : INHERITED(buffer) { 28b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com fScale256 = buffer.readUInt(); 29b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 30b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 318b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLerpXfermode::flatten(SkWriteBuffer& buffer) const { 32b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com this->INHERITED::flatten(buffer); 33b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com buffer.writeUInt(fScale256); 34b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 35b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 36b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count, 37b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com const SkAlpha aa[]) const { 38b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com const int scale = fScale256; 39b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 40b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (aa) { 41b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com for (int i = 0; i < count; ++i) { 42b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com unsigned a = aa[i]; 43b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (a) { 44b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com SkPMColor dstC = dst[i]; 45b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale); 46b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (a < 255) { 47b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7)); 48b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 49b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com dst[i] = resC; 50b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 51b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 52b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } else { 53b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com for (int i = 0; i < count; ++i) { 54b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com dst[i] = SkFastFourByteInterp256(src[i], dst[i], scale); 55b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 56b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 57b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 58b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 59b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count, 60b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com const SkAlpha aa[]) const { 61b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com const int scale = fScale256; 62b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 63b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (aa) { 64b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com for (int i = 0; i < count; ++i) { 65b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com unsigned a = aa[i]; 66b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (a) { 67b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 68b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale); 69b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (a < 255) { 70b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7)); 71b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 72b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com dst[i] = SkPixel32ToPixel16(resC); 73b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 74b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 75b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } else { 76b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com for (int i = 0; i < count; ++i) { 77b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 78b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale); 79b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com dst[i] = SkPixel32ToPixel16(resC); 80b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 81b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 82b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 83b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 84b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, 85b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com const SkAlpha aa[]) const { 86b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com const int scale = fScale256; 87b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 88b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (aa) { 89b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com for (int i = 0; i < count; ++i) { 90b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com unsigned a = aa[i]; 91b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (a) { 92b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com unsigned dstA = dst[i]; 93b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com unsigned resA = SkAlphaBlend(SkGetPackedA32(src[i]), dstA, scale); 94b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com if (a < 255) { 95b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com resA = SkAlphaBlend(resA, dstA, a + (a >> 7)); 96b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 97b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com dst[i] = resA; 98b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 99b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 100b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } else { 101b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com for (int i = 0; i < count; ++i) { 102b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com dst[i] = SkAlphaBlend(SkGetPackedA32(src[i]), dst[i], scale); 103b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 104b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com } 105b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 106b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com 1070f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 108b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::toString(SkString* str) const { 109b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com str->printf("SkLerpXfermode: scale: %g", fScale256 / 256.0); 110b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com} 111b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com#endif 112