SkBlurMask.cpp revision 543ed9352c7dfd93071c08b14930cca2e82a08d4
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/effects/SkBlurMask.cpp 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Copyright 2006, The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Licensed under the Apache License, Version 2.0 (the "License"); 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** you may not use this file except in compliance with the License. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** You may obtain a copy of the License at 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** http://www.apache.org/licenses/LICENSE-2.0 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Unless required by applicable law or agreed to in writing, software 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** distributed under the License is distributed on an "AS IS" BASIS, 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** See the License for the specific language governing permissions and 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** limitations under the License. 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMask.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void build_sum_buffer(uint32_t dst[], int w, int h, const uint8_t src[], int srcRB) 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(srcRB >= w); 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // mod srcRB so we can apply it after each row 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcRB -= w; 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x, y; 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // special case first row 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t X = 0; 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (x = w - 1; x >= 0; --x) 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com X = *src++ + X; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = X; 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += srcRB; 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now do the rest of the rows 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (y = h - 1; y > 0; --y) 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t L = 0; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t C = 0; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (x = w - 1; x >= 0; --x) 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t T = dst[-w]; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com X = *src++ + L + T - C; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = X; 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com L = X; 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com C = T; 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += srcRB; 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void apply_kernel(uint8_t dst[], int rx, int ry, const uint32_t src[], int sw, int sh) 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t scale = (1 << 24) / ((2*rx + 1)*(2*ry + 1)); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rowBytes = sw; 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dw = sw + 2*rx; 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dh = sh + 2*ry; 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sw -= 1; // now it is max_x 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sh -= 1; // now it is max_y 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prev_y = -ry - 1 -ry; 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int next_y = ry -ry; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int y = 0; y < dh; y++) 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int py = SkClampPos(prev_y) * rowBytes; 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ny = SkFastMin32(next_y, sh) * rowBytes; 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prev_x = -rx - 1 -rx; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int next_x = rx -rx; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = 0; x < dw; x++) 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int px = SkClampPos(prev_x); 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int nx = SkFastMin32(next_x, sw); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t sum = src[px+py] + src[nx+ny] - src[nx+py] - src[px+ny]; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = SkToU8(sum * scale >> 24); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev_x += 1; 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next_x += 1; 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev_y += 1; 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next_y += 1; 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void apply_kernel_interp(uint8_t dst[], int rx, int ry, const uint32_t src[], int sw, int sh, U8CPU outer_weight) 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rx > 0 && ry > 0); 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(outer_weight <= 255); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inner_weight = 255 - outer_weight; 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // round these guys up if they're bigger than 127 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com outer_weight += outer_weight >> 7; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inner_weight += inner_weight >> 7; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t outer_scale = (outer_weight << 16) / ((2*rx + 1)*(2*ry + 1)); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t inner_scale = (inner_weight << 16) / ((2*rx - 1)*(2*ry - 1)); 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rowBytes = sw; 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dw = sw + 2*rx; 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dh = sh + 2*ry; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sw -= 1; // now it is max_x 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sh -= 1; // now it is max_y 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prev_y = -ry - 1 -ry; 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int next_y = ry -ry; 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int y = 0; y < dh; y++) 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int py = SkClampPos(prev_y) * rowBytes; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ny = SkFastMin32(next_y, sh) * rowBytes; 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ipy = SkClampPos(prev_y + 1) * rowBytes; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int iny = SkClampMax(next_y - 1, sh) * rowBytes; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prev_x = -rx - 1 -rx; 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int next_x = rx -rx; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = 0; x < dw; x++) 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int px = SkClampPos(prev_x); 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int nx = SkFastMin32(next_x, sw); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ipx = SkClampPos(prev_x + 1); 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inx = SkClampMax(next_x - 1, sw); 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t outer_sum = src[px+py] + src[nx+ny] - src[nx+py] - src[px+ny]; 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t inner_sum = src[ipx+ipy] + src[inx+iny] - src[inx+ipy] - src[ipx+iny]; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = SkToU8((outer_sum * outer_scale + inner_sum * inner_scale) >> 24); 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev_x += 1; 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next_x += 1; 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev_y += 1; 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next_y += 1; 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void merge_src_with_blur(uint8_t dst[], 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t src[], int sw, int sh, 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t blur[], int blurRowBytes) 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (--sh >= 0) 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int x = sw - 1; x >= 0; --x) 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst = SkToU8(SkAlphaMul(*blur, SkAlpha255To256(*src))); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blur += 1; 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blur += blurRowBytes - sw; 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void clamp_with_orig(uint8_t dst[], int dstRowBytes, 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t src[], int sw, int sh, 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlurMask::Style style) 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (--sh >= 0) 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (style) { 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBlurMask::kSolid_Style: 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (x = sw - 1; x >= 0; --x) 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst = SkToU8(*src + SkAlphaMul(*dst, SkAlpha255To256(255 - *src))); 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBlurMask::kOuter_Style: 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (x = sw - 1; x >= 0; --x) 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (*src) 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src))); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!"Unexpected blur style here"); 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += dstRowBytes - sw; 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////// 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// we use a local funciton to wrap the class static method to work around 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// a bug in gcc98 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMask_FreeImage(uint8_t* image); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMask_FreeImage(uint8_t* image) 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(image); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBlurMask::Blur(SkMask* dst, const SkMask& src, 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar radius, Style style) 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (src.fFormat != SkMask::kA8_Format) 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rx = SkScalarCeil(radius); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int outer_weight = 255 - SkScalarRound((SkIntToScalar(rx) - radius) * 255); 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rx >= 0); 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)outer_weight <= 255); 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rx == 0) 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ry = rx; // only do square blur for now 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fBounds.set(src.fBounds.fLeft - rx, src.fBounds.fTop - ry, 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src.fBounds.fRight + rx, src.fBounds.fBottom + ry); 23149f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com dst->fRowBytes = dst->fBounds.width(); 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fFormat = SkMask::kA8_Format; 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fImage = NULL; 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (src.fImage) 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 237543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t dstSize = dst->computeImageSize(); 238543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == dstSize) { 239543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; // too big to allocate, abort 240543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 241543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sw = src.fBounds.width(); 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sh = src.fBounds.height(); 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* sp = src.fImage; 245543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com uint8_t* dp = SkMask::AllocImage(dstSize); 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // build the blurry destination 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTMalloc<uint32_t> storage(sw * sh); 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t* sumBuffer = storage.get(); 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com build_sum_buffer(sumBuffer, sw, sh, sp, src.fRowBytes); 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (outer_weight == 255) 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com apply_kernel(dp, rx, ry, sumBuffer, sw, sh); 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com apply_kernel_interp(dp, rx, ry, sumBuffer, sw, sh, outer_weight); 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fImage = dp; 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if need be, alloc the "real" dst (same size as src) and copy/merge 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the blur into it (applying the src) 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (style == kInner_Style) 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 266543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t srcSize = src.computeImageSize(); 267543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == srcSize) { 268543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; // too big to allocate, abort 269543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 270543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com dst->fImage = SkMask::AllocImage(srcSize); 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com merge_src_with_blur(dst->fImage, sp, sw, sh, 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dp + rx + ry*dst->fBounds.width(), 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fBounds.width()); 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(dp); 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (style != kNormal_Style) 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clamp_with_orig(dp + rx + ry*dst->fBounds.width(), 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fBounds.width(), 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sp, sw, sh, 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com style); 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)autoCall.detach(); 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (style == kInner_Style) 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fBounds = src.fBounds; // restore trimmed bounds 28949f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com dst->fRowBytes = dst->fBounds.width(); 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (gamma && dst->fImage) 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* image = dst->fImage; 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* stop = image + dst->computeImageSize(); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; image < stop; image += 1) 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *image = gamma[*image]; 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurMask::BuildSqrtGamma(uint8_t gamma[256], SkScalar percent) 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(gamma); 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(percent >= 0 && percent <= SK_Scalar1); 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale = SkScalarRound(percent * 256); 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 256; i++) 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed n = i * 257; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n += n >> 15; 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(n >= 0 && n <= SK_Fixed1); 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = SkFixedSqrt(n); 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = n * 255 >> 16; 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = SkAlphaBlend(n, i, scale); 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gamma[i] = SkToU8(n); 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlurMask::BuildSqrGamma(uint8_t gamma[256], SkScalar percent) 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(gamma); 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(percent >= 0 && percent <= SK_Scalar1); 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale = SkScalarRound(percent * 256); 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed div255 = SK_Fixed1 / 255; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 256; i++) 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int square = i * i; 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int linear = i * 255; 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n = SkAlphaBlend(square, linear, scale); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gamma[i] = SkToU8(n * div255 >> 16); 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 342