SkBlurMask.cpp revision 7bd141dce43ea3405bc60c9c84e6f910b851b079
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMask.h" 11889bd8bd7f604acae0a6303365bc82c06da1e6f3tomhudson@google.com#include "SkMath.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 1301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#include "SkEndian.h" 1401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com 157ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 167ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.comSkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) { 177ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // This constant approximates the scaling done in the software path's 187ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). 197ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // IMHO, it actually should be 1: we blur "less" than we should do 207ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // according to the CSS and canvas specs, simply because Safari does the same. 217ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // Firefox used to do the same too, until 4.0 where they fixed it. So at some 227ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // point we should probably get rid of these scaling constants and rebaseline 237ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // all the blur tests. 247ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com static const SkScalar kBLUR_SIGMA_SCALE = SkFloatToScalar(0.57735f); 257ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 267ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com return radius ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f; 277ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com} 287c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 299b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define UNROLL_SEPARABLE_LOOPS 309b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 31908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org/** 32908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org * This function performs a box blur in X, of the given radius. If the 33884e60be30e20f38b3466a4697081187d2f1f814skia.committer@gmail.com * "transpose" parameter is true, it will transpose the pixels on write, 34908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org * such that X and Y are swapped. Reads are always performed from contiguous 35908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org * memory in X, for speed. The destination buffer (dst) must be at least 369b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * (width + leftRadius + rightRadius) * height bytes in size. 374a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * 384a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * This is what the inner loop looks like before unrolling, and with the two 394a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * cases broken out separately (width < diameter, width >= diameter): 4076bf70d38fd109a09ee44d074cfd392e1884afffskia.committer@gmail.com * 414a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * if (width < diameter) { 424a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < width; ++x) { 434a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * sum += *right++; 4476bf70d38fd109a09ee44d074cfd392e1884afffskia.committer@gmail.com * *dptr = (sum * scale + half) >> 24; 454a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 464a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 474a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = width; x < diameter; ++x) { 484a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (sum * scale + half) >> 24; 494a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 504a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 514a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < width; ++x) { 524a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (sum * scale + half) >> 24; 534a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * sum -= *left++; 544a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 554a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 564a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } else { 574a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < diameter; ++x) { 584a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * sum += *right++; 594a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (sum * scale + half) >> 24; 604a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 614a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 624a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = diameter; x < width; ++x) { 634a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * sum += *right++; 644a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (sum * scale + half) >> 24; 654a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * sum -= *left++; 664a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 674a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 684a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < diameter; ++x) { 694a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (sum * scale + half) >> 24; 704a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * sum -= *left++; 714a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 724a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 734a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 74908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org */ 75908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.orgstatic int boxBlur(const uint8_t* src, int src_y_stride, uint8_t* dst, 76c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org int leftRadius, int rightRadius, int width, int height, 77c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org bool transpose) 7871f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org{ 799b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int diameter = leftRadius + rightRadius; 809b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int kernelSize = diameter + 1; 819b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int border = SkMin32(width, diameter); 8271f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org uint32_t scale = (1 << 24) / kernelSize; 83c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org int new_width = width + SkMax32(leftRadius, rightRadius) * 2; 84908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org int dst_x_stride = transpose ? height : 1; 85908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org int dst_y_stride = transpose ? 1 : new_width; 864a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org#ifndef SK_DISABLE_BLUR_ROUNDING 874a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org uint32_t half = 1 << 23; 884a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org#else 894a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org uint32_t half = 0; 904a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org#endif 9171f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org for (int y = 0; y < height; ++y) { 924a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org uint32_t sum = 0; 93908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org uint8_t* dptr = dst + y * dst_y_stride; 94908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org const uint8_t* right = src + y * src_y_stride; 95908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org const uint8_t* left = right; 96336b4da6b0d20f27f9980b03415354a2f0698e18senorblanco@chromium.org for (int x = 0; x < rightRadius - leftRadius; x++) { 97336b4da6b0d20f27f9980b03415354a2f0698e18senorblanco@chromium.org *dptr = 0; 98336b4da6b0d20f27f9980b03415354a2f0698e18senorblanco@chromium.org dptr += dst_x_stride; 99c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org } 1009b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define LEFT_BORDER_ITER \ 1019b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org sum += *right++; \ 1024a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (sum * scale + half) >> 24; \ 103908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org dptr += dst_x_stride; 1049b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 1059b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int x = 0; 1069b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 1079b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < border - 16; x += 16) { 1089b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1099b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1109b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1119b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1129b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1139b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1149b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1159b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1169b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1179b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1189b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1199b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1209b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1219b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1229b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1239b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 12471f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } 1259b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 1269b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < border; ++x) { 1279b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 1289b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 1299b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef LEFT_BORDER_ITER 1309b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define TRIVIAL_ITER \ 1314a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (sum * scale + half) >> 24; \ 132908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org dptr += dst_x_stride; 1339b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org x = width; 1349b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 1359b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < diameter - 16; x += 16) { 1369b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1379b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1389b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1399b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1409b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1419b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1429b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1439b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1449b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1459b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1469b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1479b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1489b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1499b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1509b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1519b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 1529b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 1539b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 1549b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < diameter; ++x) { 1559b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org TRIVIAL_ITER 15671f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } 1579b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef TRIVIAL_ITER 1589b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define CENTER_ITER \ 1599b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org sum += *right++; \ 1604a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (sum * scale + half) >> 24; \ 1619b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org sum -= *left++; \ 162908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org dptr += dst_x_stride; 1639b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 1649b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org x = diameter; 1659b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 1669b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < width - 16; x += 16) { 1679b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1689b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1699b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1709b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1719b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1729b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1739b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1749b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1759b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1769b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1779b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1789b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1799b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1809b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1819b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1829b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 1839b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 1849b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 1859b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < width; ++x) { 1869b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 18771f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } 1889b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef CENTER_ITER 1899b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define RIGHT_BORDER_ITER \ 1904a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (sum * scale + half) >> 24; \ 1919b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org sum -= *left++; \ 192908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org dptr += dst_x_stride; 1939b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 1949b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org x = 0; 1959b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 1969b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < border - 16; x += 16) { 1979b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 1989b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 1999b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2009b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2019b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2029b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2039b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2049b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2059b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2069b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2079b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2089b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2099b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2109b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2119b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2129b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 2139b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 2149b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 2159b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < border; ++x) { 2169b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 21771f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } 2189b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef RIGHT_BORDER_ITER 219a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = 0; x < leftRadius - rightRadius; ++x) { 220336b4da6b0d20f27f9980b03415354a2f0698e18senorblanco@chromium.org *dptr = 0; 221336b4da6b0d20f27f9980b03415354a2f0698e18senorblanco@chromium.org dptr += dst_x_stride; 222c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org } 22371f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org SkASSERT(sum == 0); 22471f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } 225908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org return new_width; 22671f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org} 22771f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org 2289b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org/** 2299b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * This variant of the box blur handles blurring of non-integer radii. It 2309b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * keeps two running sums: an outer sum for the rounded-up kernel radius, and 2319b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * an inner sum for the rounded-down kernel radius. For each pixel, it linearly 2329b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * interpolates between them. In float this would be: 2339b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * outer_weight * outer_sum / kernelSize + 2349b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org * (1.0 - outer_weight) * innerSum / (kernelSize - 2) 23576bf70d38fd109a09ee44d074cfd392e1884afffskia.committer@gmail.com * 2364a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * This is what the inner loop looks like before unrolling, and with the two 2374a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * cases broken out separately (width < diameter, width >= diameter): 23876bf70d38fd109a09ee44d074cfd392e1884afffskia.committer@gmail.com * 2394a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * if (width < diameter) { 2404a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < width; x++) { 2414a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * inner_sum = outer_sum; 2424a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * outer_sum += *right++; 2434a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 2444a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 2454a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2464a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = width; x < diameter; ++x) { 2474a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 2484a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 2494a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2504a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < width; x++) { 2514a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * inner_sum = outer_sum - *left++; 2524a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 2534a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 2544a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * outer_sum = inner_sum; 2554a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2564a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } else { 2574a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < diameter; x++) { 2584a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * inner_sum = outer_sum; 2594a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * outer_sum += *right++; 2604a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 2614a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 2624a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2634a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = diameter; x < width; ++x) { 2644a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * inner_sum = outer_sum - *left; 2654a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * outer_sum += *right++; 2664a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 2674a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 2684a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * outer_sum -= *left++; 2694a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2704a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * for (int x = 0; x < diameter; x++) { 2714a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * inner_sum = outer_sum - *left++; 2724a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 2734a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * dptr += dst_x_stride; 2744a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * outer_sum = inner_sum; 2754a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2764a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2774a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * } 2784a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org * return new_width; 2799b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org */ 2804a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org 2819b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.orgstatic int boxBlurInterp(const uint8_t* src, int src_y_stride, uint8_t* dst, 2829b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int radius, int width, int height, 2839b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org bool transpose, uint8_t outer_weight) 2849b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org{ 2859b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int diameter = radius * 2; 2869b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int kernelSize = diameter + 1; 2879b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int border = SkMin32(width, diameter); 2889b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int inner_weight = 255 - outer_weight; 2899b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org outer_weight += outer_weight >> 7; 2909b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org inner_weight += inner_weight >> 7; 2919b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org uint32_t outer_scale = (outer_weight << 16) / kernelSize; 2929b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org uint32_t inner_scale = (inner_weight << 16) / (kernelSize - 2); 2934a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org#ifndef SK_DISABLE_BLUR_ROUNDING 2944a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org uint32_t half = 1 << 23; 2954a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org#else 2964a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org uint32_t half = 0; 2974a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org#endif 2989b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int new_width = width + diameter; 2999b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int dst_x_stride = transpose ? height : 1; 3009b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int dst_y_stride = transpose ? 1 : new_width; 3019b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (int y = 0; y < height; ++y) { 3024a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org uint32_t outer_sum = 0, inner_sum = 0; 3039b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org uint8_t* dptr = dst + y * dst_y_stride; 3049b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org const uint8_t* right = src + y * src_y_stride; 3059b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org const uint8_t* left = right; 3069b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org int x = 0; 3079b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 3089b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define LEFT_BORDER_ITER \ 3099b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org inner_sum = outer_sum; \ 3109b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org outer_sum += *right++; \ 3114a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; \ 3129b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org dptr += dst_x_stride; 3139b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 3149b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 3159b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (;x < border - 16; x += 16) { 3169b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3179b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3189b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3199b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3209b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3219b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3229b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3239b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3249b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3259b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3269b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3279b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3289b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3299b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3309b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3319b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3329b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 3339b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 3349b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 335a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (;x < border; ++x) { 3369b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org LEFT_BORDER_ITER 3379b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 3389b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef LEFT_BORDER_ITER 3399b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (int x = width; x < diameter; ++x) { 3404a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; 3419b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org dptr += dst_x_stride; 3429b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 3439b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org x = diameter; 3449b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 3459b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#define CENTER_ITER \ 3469b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org inner_sum = outer_sum - *left; \ 3479b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org outer_sum += *right++; \ 3484a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; \ 3499b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org dptr += dst_x_stride; \ 3509b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org outer_sum -= *left++; 3519b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 3529b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 3539b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < width - 16; x += 16) { 3549b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3559b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3569b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3579b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3589b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3599b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3609b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3619b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3629b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3639b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3649b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3659b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3669b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3679b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3689b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3699b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3709b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 3719b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 3729b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < width; ++x) { 3739b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org CENTER_ITER 3749b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 3759b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef CENTER_ITER 3769b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 3779b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org #define RIGHT_BORDER_ITER \ 3789b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org inner_sum = outer_sum - *left++; \ 3794a525d7fc2cc0d8029bc66095730ddba3df3cb9esenorblanco@chromium.org *dptr = (outer_sum * outer_scale + inner_sum * inner_scale + half) >> 24; \ 3809b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org dptr += dst_x_stride; \ 3819b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org outer_sum = inner_sum; 3829b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 3839b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org x = 0; 3849b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#ifdef UNROLL_SEPARABLE_LOOPS 3859b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org for (; x < border - 16; x += 16) { 3869b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3879b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3889b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3899b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3909b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3919b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3929b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3939b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3949b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3959b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3969b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3979b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3989b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 3999b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 4009b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 4019b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 4029b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 4039b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#endif 404a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (; x < border; ++x) { 4059b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org RIGHT_BORDER_ITER 4069b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 4079b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org#undef RIGHT_BORDER_ITER 4089b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org SkASSERT(outer_sum == 0 && inner_sum == 0); 4099b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org } 4109b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org return new_width; 4119b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org} 4129b0d4d79f023ce91b53d9eaa47508b6722c246e6senorblanco@chromium.org 413c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.orgstatic void get_adjusted_radii(SkScalar passRadius, int *loRadius, int *hiRadius) 414c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org{ 415c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org *loRadius = *hiRadius = SkScalarCeil(passRadius); 416c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org if (SkIntToScalar(*hiRadius) - passRadius > SkFloatToScalar(0.5f)) { 417c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org *loRadius = *hiRadius - 1; 418c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org } 419c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org} 420c4381309649c5cf338dcf6a7fc8296451a686d6bsenorblanco@chromium.org 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4230e3c664250f561ec9f7107b92136517a72d03afdreed@android.comstatic void merge_src_with_blur(uint8_t dst[], int dstRB, 4240e3c664250f561ec9f7107b92136517a72d03afdreed@android.com const uint8_t src[], int srcRB, 4250e3c664250f561ec9f7107b92136517a72d03afdreed@android.com const uint8_t blur[], int blurRB, 4260e3c664250f561ec9f7107b92136517a72d03afdreed@android.com int sw, int sh) { 4270e3c664250f561ec9f7107b92136517a72d03afdreed@android.com dstRB -= sw; 4280e3c664250f561ec9f7107b92136517a72d03afdreed@android.com srcRB -= sw; 4290e3c664250f561ec9f7107b92136517a72d03afdreed@android.com blurRB -= sw; 4300e3c664250f561ec9f7107b92136517a72d03afdreed@android.com while (--sh >= 0) { 4310e3c664250f561ec9f7107b92136517a72d03afdreed@android.com for (int x = sw - 1; x >= 0; --x) { 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst = SkToU8(SkAlphaMul(*blur, SkAlpha255To256(*src))); 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blur += 1; 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4370e3c664250f561ec9f7107b92136517a72d03afdreed@android.com dst += dstRB; 4380e3c664250f561ec9f7107b92136517a72d03afdreed@android.com src += srcRB; 4390e3c664250f561ec9f7107b92136517a72d03afdreed@android.com blur += blurRB; 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void clamp_with_orig(uint8_t dst[], int dstRowBytes, 4440e3c664250f561ec9f7107b92136517a72d03afdreed@android.com const uint8_t src[], int srcRowBytes, 4450e3c664250f561ec9f7107b92136517a72d03afdreed@android.com int sw, int sh, 4464560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com SkBlurMask::Style style) { 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x; 4480e3c664250f561ec9f7107b92136517a72d03afdreed@android.com while (--sh >= 0) { 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (style) { 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBlurMask::kSolid_Style: 4510e3c664250f561ec9f7107b92136517a72d03afdreed@android.com for (x = sw - 1; x >= 0; --x) { 4520e3c664250f561ec9f7107b92136517a72d03afdreed@android.com int s = *src; 4530e3c664250f561ec9f7107b92136517a72d03afdreed@android.com int d = *dst; 4540e3c664250f561ec9f7107b92136517a72d03afdreed@android.com *dst = SkToU8(s + d - SkMulDiv255Round(s, d)); 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBlurMask::kOuter_Style: 4600e3c664250f561ec9f7107b92136517a72d03afdreed@android.com for (x = sw - 1; x >= 0; --x) { 4610e3c664250f561ec9f7107b92136517a72d03afdreed@android.com if (*src) { 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src))); 4630e3c664250f561ec9f7107b92136517a72d03afdreed@android.com } 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 4690c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("Unexpected blur style here"); 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += dstRowBytes - sw; 4730e3c664250f561ec9f7107b92136517a72d03afdreed@android.com src += srcRowBytes - sw; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 47703016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com/////////////////////////////////////////////////////////////////////////////// 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 47933cdbdea3ddcec9323b65eace86e10557312ae9bbsalomon@google.com// we use a local function to wrap the class static method to work around 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// a bug in gcc98 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMask_FreeImage(uint8_t* image); 48203016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.comvoid SkMask_FreeImage(uint8_t* image) { 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(image); 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBlurMask::Blur(SkMask* dst, const SkMask& src, 4875af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkScalar radius, Style style, Quality quality, 4887ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkIPoint* margin) { 4897bd141dce43ea3405bc60c9c84e6f910b851b079skia.committer@gmail.com return SkBlurMask::BoxBlur(dst, src, 4907ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkBlurMask::ConvertRadiusToSigma(radius), 4917ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com style, quality, margin); 4927ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com} 4937ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 4947ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.combool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, 4957ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar sigma, Style style, Quality quality, 4967ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkIPoint* margin) { 497a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 49803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com if (src.fFormat != SkMask::kA8_Format) { 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 50003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com } 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5024868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org // Force high quality off for small radii (performance) 5037ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com if (sigma <= SkIntToScalar(2)) { 50491f489a65d436d36c7fe580af2775cd0cd13c8d2senorblanco@chromium.org quality = kLow_Quality; 50591f489a65d436d36c7fe580af2775cd0cd13c8d2senorblanco@chromium.org } 506d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 5077ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar passRadius; 5087ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com if (kHigh_Quality == quality) { 5097ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // For the high quality path the 3 pass box blur kernel width is 5107ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // 6*rad+1 while the full Gaussian width is 6*sigma. 5117ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com passRadius = sigma - (1/6.0f); 5127ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com } else { 5137bd141dce43ea3405bc60c9c84e6f910b851b079skia.committer@gmail.com // For the low quality path we only attempt to cover 3*sigma of the 5147bd141dce43ea3405bc60c9c84e6f910b851b079skia.committer@gmail.com // Gaussian blur area (1.5*sigma on each side). The single pass box 5157ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com // blur's kernel size is 2*rad+1. 5167ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com passRadius = 1.5f*sigma - 0.5f; 5177ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com } 5187ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 519d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com // highQuality: use three box blur passes as a cheap way 520a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // to approximate a Gaussian blur 52191f489a65d436d36c7fe580af2775cd0cd13c8d2senorblanco@chromium.org int passCount = (kHigh_Quality == quality) ? 3 : 1; 522a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 5234868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org int rx = SkScalarCeil(passRadius); 524a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int outerWeight = 255 - SkScalarRound((SkIntToScalar(rx) - passRadius) * 255); 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rx >= 0); 527a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkASSERT((unsigned)outerWeight <= 255); 5280e3c664250f561ec9f7107b92136517a72d03afdreed@android.com if (rx <= 0) { 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5300e3c664250f561ec9f7107b92136517a72d03afdreed@android.com } 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ry = rx; // only do square blur for now 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5344868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org int padx = passCount * rx; 5354868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org int pady = passCount * ry; 536d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 5375af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (margin) { 5385af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com margin->set(padx, pady); 5395af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 5404868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady, 5417ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com src.fBounds.fRight + padx, src.fBounds.fBottom + pady); 542d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 54349f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com dst->fRowBytes = dst->fBounds.width(); 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fFormat = SkMask::kA8_Format; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fImage = NULL; 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5470e3c664250f561ec9f7107b92136517a72d03afdreed@android.com if (src.fImage) { 548543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t dstSize = dst->computeImageSize(); 549543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == dstSize) { 550543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; // too big to allocate, abort 551543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 552543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sw = src.fBounds.width(); 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sh = src.fBounds.height(); 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* sp = src.fImage; 556543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com uint8_t* dp = SkMask::AllocImage(dstSize); 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // build the blurry destination 5600a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org SkAutoTMalloc<uint8_t> tmpBuffer(dstSize); 5610a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org uint8_t* tp = tmpBuffer.get(); 5620a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org int w = sw, h = sh; 563d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 5640a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org if (outerWeight == 255) { 5650a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org int loRadius, hiRadius; 5660a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org get_adjusted_radii(passRadius, &loRadius, &hiRadius); 5670a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org if (kHigh_Quality == quality) { 5680a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org // Do three X blurs, with a transpose on the final one. 5690a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, false); 5700a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlur(tp, w, dp, hiRadius, loRadius, w, h, false); 5710a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlur(dp, w, tp, hiRadius, hiRadius, w, h, true); 5720a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org // Do three Y blurs, with a transpose on the final one. 5730a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlur(tp, h, dp, loRadius, hiRadius, h, w, false); 5740a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlur(dp, h, tp, hiRadius, loRadius, h, w, false); 5750a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlur(tp, h, dp, hiRadius, hiRadius, h, w, true); 576908276b3969cf8f8eec28026363897134c0e54e0senorblanco@chromium.org } else { 5770a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlur(sp, src.fRowBytes, tp, rx, rx, w, h, true); 5780a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlur(tp, h, dp, ry, ry, h, w, true); 57971f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } 58071f0f34f7d8e80fe760f318f29ba88ab58baff7dsenorblanco@chromium.org } else { 58191f489a65d436d36c7fe580af2775cd0cd13c8d2senorblanco@chromium.org if (kHigh_Quality == quality) { 5820a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org // Do three X blurs, with a transpose on the final one. 5830a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outerWeight); 5840a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlurInterp(tp, w, dp, rx, w, h, false, outerWeight); 5850a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlurInterp(dp, w, tp, rx, w, h, true, outerWeight); 5860a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org // Do three Y blurs, with a transpose on the final one. 5870a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlurInterp(tp, h, dp, ry, h, w, false, outerWeight); 5880a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlurInterp(dp, h, tp, ry, h, w, false, outerWeight); 5890a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWeight); 5900a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org } else { 5910a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outerWeight); 5920a1c3872de6642ada98bd7226ff9ed14750241b9commit-bot@chromium.org h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWeight); 5934868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org } 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fImage = dp; 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if need be, alloc the "real" dst (same size as src) and copy/merge 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the blur into it (applying the src) 5990e3c664250f561ec9f7107b92136517a72d03afdreed@android.com if (style == kInner_Style) { 6000e3c664250f561ec9f7107b92136517a72d03afdreed@android.com // now we allocate the "real" dst, mirror the size of src 601543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t srcSize = src.computeImageSize(); 602543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == srcSize) { 603543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; // too big to allocate, abort 604543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 605543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com dst->fImage = SkMask::AllocImage(srcSize); 6060e3c664250f561ec9f7107b92136517a72d03afdreed@android.com merge_src_with_blur(dst->fImage, src.fRowBytes, 6070e3c664250f561ec9f7107b92136517a72d03afdreed@android.com sp, src.fRowBytes, 60803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com dp + passCount * (rx + ry * dst->fRowBytes), 60903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com dst->fRowBytes, sw, sh); 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(dp); 6110e3c664250f561ec9f7107b92136517a72d03afdreed@android.com } else if (style != kNormal_Style) { 61203016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes), 61303016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com dst->fRowBytes, sp, src.fRowBytes, sw, sh, style); 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)autoCall.detach(); 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6180e3c664250f561ec9f7107b92136517a72d03afdreed@android.com if (style == kInner_Style) { 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fBounds = src.fBounds; // restore trimmed bounds 6200e3c664250f561ec9f7107b92136517a72d03afdreed@android.com dst->fRowBytes = src.fRowBytes; 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6267c7292c6071898d73dc935c3b66b9816183806f0humper@google.com/* Convolving a box with itself three times results in a piecewise 6277c7292c6071898d73dc935c3b66b9816183806f0humper@google.com quadratic function: 6288ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 6297c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 0 x <= -1.5 630a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 9/8 + 3/2 x + 1/2 x^2 -1.5 < x <= -.5 6317c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 3/4 - x^2 -.5 < x <= .5 6327c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 9/8 - 3/2 x + 1/2 x^2 0.5 < x <= 1.5 6337c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 0 1.5 < x 634d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 635a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com Mathematica: 636d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 637a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com g[x_] := Piecewise [ { 638a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com {9/8 + 3/2 x + 1/2 x^2 , -1.5 < x <= -.5}, 639a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com {3/4 - x^2 , -.5 < x <= .5}, 640a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com {9/8 - 3/2 x + 1/2 x^2 , 0.5 < x <= 1.5} 641a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com }, 0] 6428ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 6437c7292c6071898d73dc935c3b66b9816183806f0humper@google.com To get the profile curve of the blurred step function at the rectangle 6447c7292c6071898d73dc935c3b66b9816183806f0humper@google.com edge, we evaluate the indefinite integral, which is piecewise cubic: 6458ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 6467c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 0 x <= -1.5 647a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 9/16 + 9/8 x + 3/4 x^2 + 1/6 x^3 -1.5 < x <= -0.5 6487c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 1/2 + 3/4 x - 1/3 x^3 -.5 < x <= .5 649a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 7/16 + 9/8 x - 3/4 x^2 + 1/6 x^3 .5 < x <= 1.5 6507c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 1 1.5 < x 651d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 652a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com in Mathematica code: 653d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 654a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com gi[x_] := Piecewise[ { 655a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com { 0 , x <= -1.5 }, 656a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com { 9/16 + 9/8 x + 3/4 x^2 + 1/6 x^3, -1.5 < x <= -0.5 }, 657a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com { 1/2 + 3/4 x - 1/3 x^3 , -.5 < x <= .5}, 658a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com { 7/16 + 9/8 x - 3/4 x^2 + 1/6 x^3, .5 < x <= 1.5} 659a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com },1] 6607c7292c6071898d73dc935c3b66b9816183806f0humper@google.com*/ 6617c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 662a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.comstatic float gaussianIntegral(float x) { 663a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (x > 1.5f) { 6647c7292c6071898d73dc935c3b66b9816183806f0humper@google.com return 0.0f; 6657c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 666a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (x < -1.5f) { 6677c7292c6071898d73dc935c3b66b9816183806f0humper@google.com return 1.0f; 6687c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 6697c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 6707c7292c6071898d73dc935c3b66b9816183806f0humper@google.com float x2 = x*x; 6717c7292c6071898d73dc935c3b66b9816183806f0humper@google.com float x3 = x2*x; 6727c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 6739c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com if ( x > 0.5f ) { 674a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return 0.5625f - (x3 / 6.0f - 3.0f * x2 * 0.25f + 1.125f * x); 6757c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 6769c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com if ( x > -0.5f ) { 6779c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com return 0.5f - (0.75f * x - x3 / 3.0f); 6787c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 6799c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x); 6807c7292c6071898d73dc935c3b66b9816183806f0humper@google.com} 6817c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 6827c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com/* compute_profile allocates and fills in an array of floating 6838ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com point values between 0 and 255 for the profile signature of 6847c7292c6071898d73dc935c3b66b9816183806f0humper@google.com a blurred half-plane with the given blur radius. Since we're 6857c7292c6071898d73dc935c3b66b9816183806f0humper@google.com going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) 6867c7292c6071898d73dc935c3b66b9816183806f0humper@google.com all the time, we actually fill in the profile pre-inverted 6877c7292c6071898d73dc935c3b66b9816183806f0humper@google.com (already done 255-x). 6888ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 6897c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com It's the responsibility of the caller to delete the 6907c7292c6071898d73dc935c3b66b9816183806f0humper@google.com memory returned in profile_out. 6917c7292c6071898d73dc935c3b66b9816183806f0humper@google.com*/ 6927c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 6937ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.comstatic void compute_profile(SkScalar sigma, unsigned int **profile_out) { 6947ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com int size = SkScalarCeilToInt(6*sigma); 6952e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 6967c7292c6071898d73dc935c3b66b9816183806f0humper@google.com int center = size >> 1; 69733cdbdea3ddcec9323b65eace86e10557312ae9bbsalomon@google.com unsigned int *profile = SkNEW_ARRAY(unsigned int, size); 6987c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 6997ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float invr = 1.f/(2*sigma); 7007c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 7017c7292c6071898d73dc935c3b66b9816183806f0humper@google.com profile[0] = 255; 702a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = 1 ; x < size ; ++x) { 703d98df1a3c468a2a7a5fff5efbf6dbdaf077d1abejvanverth@google.com float scaled_x = (center - x - .5f) * invr; 704a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float gi = gaussianIntegral(scaled_x); 705a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com profile[x] = 255 - (uint8_t) (255.f * gi); 7067c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 7077c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 7087c7292c6071898d73dc935c3b66b9816183806f0humper@google.com *profile_out = profile; 7097c7292c6071898d73dc935c3b66b9816183806f0humper@google.com} 7107c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 7118ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com// TODO MAYBE: Maintain a profile cache to avoid recomputing this for 7127c7292c6071898d73dc935c3b66b9816183806f0humper@google.com// commonly used radii. Consider baking some of the most common blur radii 7137c7292c6071898d73dc935c3b66b9816183806f0humper@google.com// directly in as static data? 7147c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 7157c7292c6071898d73dc935c3b66b9816183806f0humper@google.com// Implementation adapted from Michael Herf's approach: 7167c7292c6071898d73dc935c3b66b9816183806f0humper@google.com// http://stereopsis.com/shadowrect/ 7177c7292c6071898d73dc935c3b66b9816183806f0humper@google.com 718a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.comstatic inline unsigned int profile_lookup( unsigned int *profile, int loc, int blurred_width, int sharp_width ) { 719a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far are we from the original edge? 720a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int ox = dx >> 1; 721a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (ox < 0) { 722a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com ox = 0; 723a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 724d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 725a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return profile[ox]; 726a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com} 727a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 7287c7292c6071898d73dc935c3b66b9816183806f0humper@google.combool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src, 7297ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar radius, Style style, 7307c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com SkIPoint *margin, SkMask::CreateMode createMode) { 7317ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius), 7327bd141dce43ea3405bc60c9c84e6f910b851b079skia.committer@gmail.com dst, src, 7337ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com style, margin, createMode); 7347ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com} 7358ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7367bd141dce43ea3405bc60c9c84e6f910b851b079skia.committer@gmail.combool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst, 7377ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com const SkRect &src, Style style, 7387ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkIPoint *margin, SkMask::CreateMode createMode) { 7397ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com int profile_size = SkScalarCeilToInt(6*sigma); 7402e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 741a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int pad = profile_size/2; 7427c7292c6071898d73dc935c3b66b9816183806f0humper@google.com if (margin) { 7437c7292c6071898d73dc935c3b66b9816183806f0humper@google.com margin->set( pad, pad ); 7447c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 745d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 7462e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com dst->fBounds.set(SkScalarRoundToInt(src.fLeft - pad), 7472e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com SkScalarRoundToInt(src.fTop - pad), 7482e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com SkScalarRoundToInt(src.fRight + pad), 74968a690cb05d78060a95b1c8af0e60467740730a4humper@google.com SkScalarRoundToInt(src.fBottom + pad)); 7508ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7517c7292c6071898d73dc935c3b66b9816183806f0humper@google.com dst->fRowBytes = dst->fBounds.width(); 7527c7292c6071898d73dc935c3b66b9816183806f0humper@google.com dst->fFormat = SkMask::kA8_Format; 7537c7292c6071898d73dc935c3b66b9816183806f0humper@google.com dst->fImage = NULL; 7542e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 7557c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com int sw = SkScalarFloorToInt(src.width()); 7567c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com int sh = SkScalarFloorToInt(src.height()); 7572e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 7587c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com if (createMode == SkMask::kJustComputeBounds_CreateMode) { 7597c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com if (style == kInner_Style) { 7602e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com dst->fBounds.set(SkScalarRoundToInt(src.fLeft), 7612e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com SkScalarRoundToInt(src.fTop), 7622e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com SkScalarRoundToInt(src.fRight), 76368a690cb05d78060a95b1c8af0e60467740730a4humper@google.com SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds 7647c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com dst->fRowBytes = sw; 7657c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } 7667c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com return true; 7677c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } 7687c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com unsigned int *profile = NULL; 7692e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 7707ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com compute_profile(sigma, &profile); 7717c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com SkAutoTDeleteArray<unsigned int> ada(profile); 7722e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 7737c7292c6071898d73dc935c3b66b9816183806f0humper@google.com size_t dstSize = dst->computeImageSize(); 7747c7292c6071898d73dc935c3b66b9816183806f0humper@google.com if (0 == dstSize) { 7757c7292c6071898d73dc935c3b66b9816183806f0humper@google.com return false; // too big to allocate, abort 7767c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 7778ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7787c7292c6071898d73dc935c3b66b9816183806f0humper@google.com uint8_t* dp = SkMask::AllocImage(dstSize); 7798ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7807c7292c6071898d73dc935c3b66b9816183806f0humper@google.com dst->fImage = dp; 7818ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 782a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int dstHeight = dst->fBounds.height(); 783a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int dstWidth = dst->fBounds.width(); 7848ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7857c7292c6071898d73dc935c3b66b9816183806f0humper@google.com // nearest odd number less than the profile size represents the center 7867c7292c6071898d73dc935c3b66b9816183806f0humper@google.com // of the (2x scaled) profile 7877c7292c6071898d73dc935c3b66b9816183806f0humper@google.com int center = ( profile_size & ~1 ) - 1; 7888ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7897c7292c6071898d73dc935c3b66b9816183806f0humper@google.com int w = sw - center; 7907c7292c6071898d73dc935c3b66b9816183806f0humper@google.com int h = sh - center; 7918ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 7927c7292c6071898d73dc935c3b66b9816183806f0humper@google.com uint8_t *outptr = dp; 793d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 794a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth); 7958ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 796a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = 0 ; x < dstWidth ; ++x) { 797a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (profile_size <= sw) { 798a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com horizontalScanline[x] = profile_lookup(profile, x, dstWidth, w); 799a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } else { 8007ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float span = float(sw)/(2*sigma); 8017ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float giX = 1.5f - (x+.5f)/(2*sigma); 802a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com horizontalScanline[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span))); 803a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 804a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 805d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 806a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int y = 0 ; y < dstHeight ; ++y) { 807a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com unsigned int profile_y; 808a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (profile_size <= sh) { 809a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com profile_y = profile_lookup(profile, y, dstHeight, h); 810a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } else { 8117ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float span = float(sh)/(2*sigma); 8127ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float giY = 1.5f - (y+.5f)/(2*sigma); 813a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com profile_y = (uint8_t) (255 * (gaussianIntegral(giY) - gaussianIntegral(giY + span))); 814a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 8158ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 816a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = 0 ; x < dstWidth ; x++) { 817a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], profile_y); 818a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com *(outptr++) = maskval; 819a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 820a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 821d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 822a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (style == kInner_Style) { 823a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // now we allocate the "real" dst, mirror the size of src 824d98df1a3c468a2a7a5fff5efbf6dbdaf077d1abejvanverth@google.com size_t srcSize = (size_t)(src.width() * src.height()); 825a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (0 == srcSize) { 826a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return false; // too big to allocate, abort 827a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 828a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fImage = SkMask::AllocImage(srcSize); 829a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int y = 0 ; y < sh ; y++) { 830a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad; 831a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t *inner_scanline = dst->fImage + y*sw; 832a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com memcpy(inner_scanline, blur_scanline, sw); 833a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 834a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkMask::FreeImage(dp); 835a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 8362e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com dst->fBounds.set(SkScalarRoundToInt(src.fLeft), 8372e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com SkScalarRoundToInt(src.fTop), 8382e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com SkScalarRoundToInt(src.fRight), 83968a690cb05d78060a95b1c8af0e60467740730a4humper@google.com SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds 840a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fRowBytes = sw; 841d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 842a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } else if (style == kOuter_Style) { 843a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int y = pad ; y < dstHeight-pad ; y++) { 844a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t *dst_scanline = dp + y*dstWidth + pad; 845a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com memset(dst_scanline, 0, sw); 846a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 847d4d573057ee126bae354934b8d31f5695af387b6humper@google.com } else if (style == kSolid_Style) { 848d4d573057ee126bae354934b8d31f5695af387b6humper@google.com for (int y = pad ; y < dstHeight-pad ; y++) { 849d4d573057ee126bae354934b8d31f5695af387b6humper@google.com uint8_t *dst_scanline = dp + y*dstWidth + pad; 850d4d573057ee126bae354934b8d31f5695af387b6humper@google.com memset(dst_scanline, 0xff, sw); 8512e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com } 852a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 853a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // normal and solid styles are the same for analytic rect blurs, so don't 854a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // need to handle solid specially. 8558ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 856a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return true; 857a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com} 8588ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 8597ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.combool SkBlurMask::BlurGroundTruth(SkMask* dst, const SkMask& src, SkScalar radius, 8607ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com Style style, SkIPoint* margin) { 8617ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com return BlurGroundTruth(ConvertRadiusToSigma(radius), dst, src, style, margin); 8627ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com} 863a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com// The "simple" blur is a direct implementation of separable convolution with a discrete 864a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com// gaussian kernel. It's "ground truth" in a sense; too slow to be used, but very 865a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com// useful for correctness comparisons. 8668ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 8677ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.combool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, 8687ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com Style style, SkIPoint* margin) { 869d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 870a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (src.fFormat != SkMask::kA8_Format) { 871a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return false; 872a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 8738ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 8747ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float variance = sigma * sigma; 875a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 8767ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com int windowSize = SkScalarCeil(sigma*4); 877a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // round window size up to nearest odd number 878a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com windowSize |= 1; 879a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 880a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkAutoTMalloc<float> gaussWindow(windowSize); 881a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 882a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int halfWindow = windowSize >> 1; 883d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 884a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com gaussWindow[halfWindow] = 1; 885d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 886a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float windowSum = 1; 887a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = 1 ; x <= halfWindow ; ++x) { 888a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float gaussian = expf(-x*x / variance); 889a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com gaussWindow[halfWindow + x] = gaussWindow[halfWindow-x] = gaussian; 890a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com windowSum += 2*gaussian; 891a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 892a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 893a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // leave the filter un-normalized for now; we will divide by the normalization 894a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // sum later; 895d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 896a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int pad = halfWindow; 897a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (margin) { 898a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com margin->set( pad, pad ); 899a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 900a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 901a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fBounds = src.fBounds; 902a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fBounds.outset(pad, pad); 903a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 904a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fRowBytes = dst->fBounds.width(); 905a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fFormat = SkMask::kA8_Format; 906a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fImage = NULL; 907a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 908a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (src.fImage) { 909a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 910a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com size_t dstSize = dst->computeImageSize(); 911a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (0 == dstSize) { 912a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return false; // too big to allocate, abort 913a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 914d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 915a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int srcWidth = src.fBounds.width(); 916a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int srcHeight = src.fBounds.height(); 917a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int dstWidth = dst->fBounds.width(); 918d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 919a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com const uint8_t* srcPixels = src.fImage; 920a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t* dstPixels = SkMask::AllocImage(dstSize); 921a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dstPixels); 922a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 923a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // do the actual blur. First, make a padded copy of the source. 924a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // use double pad so we never have to check if we're outside anything 925d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 926a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int padWidth = srcWidth + 4*pad; 927a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int padHeight = srcHeight; 928a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int padSize = padWidth * padHeight; 929d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 930a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkAutoTMalloc<uint8_t> padPixels(padSize); 931a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com memset(padPixels, 0, padSize); 932d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 933a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int y = 0 ; y < srcHeight; ++y) { 934a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t* padptr = padPixels + y * padWidth + 2*pad; 935a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com const uint8_t* srcptr = srcPixels + y * srcWidth; 936a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com memcpy(padptr, srcptr, srcWidth); 937a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 938d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 939a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // blur in X, transposing the result into a temporary floating point buffer. 940a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // also double-pad the intermediate result so that the second blur doesn't 941a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // have to do extra conditionals. 942d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 943a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int tmpWidth = padHeight + 4*pad; 944a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int tmpHeight = padWidth - 2*pad; 945a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int tmpSize = tmpWidth * tmpHeight; 946d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 947a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkAutoTMalloc<float> tmpImage(tmpSize); 948a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com memset(tmpImage, 0, tmpSize*sizeof(tmpImage[0])); 949a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 950a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int y = 0 ; y < padHeight ; ++y) { 951a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t *srcScanline = padPixels + y*padWidth; 952a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = pad ; x < padWidth - pad ; ++x) { 953a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float *outPixel = tmpImage + (x-pad)*tmpWidth + y + 2*pad; // transposed output 954a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t *windowCenter = srcScanline + x; 955a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int i = -pad ; i <= pad ; ++i) { 956a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com *outPixel += gaussWindow[pad+i]*windowCenter[i]; 957a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 958a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com *outPixel /= windowSum; 959d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com } 960a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 961d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 962a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // blur in Y; now filling in the actual desired destination. We have to do 963d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com // the transpose again; these transposes guarantee that we read memory in 964a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // linear order. 965d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 966a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int y = 0 ; y < tmpHeight ; ++y) { 967a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float *srcScanline = tmpImage + y*tmpWidth; 968a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int x = pad ; x < tmpWidth - pad ; ++x) { 969a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float *windowCenter = srcScanline + x; 970a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com float finalValue = 0; 971a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com for (int i = -pad ; i <= pad ; ++i) { 972a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com finalValue += gaussWindow[pad+i]*windowCenter[i]; 973a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 974a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com finalValue /= windowSum; 975a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com uint8_t *outPixel = dstPixels + (x-pad)*dstWidth + y; // transposed output 976a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com int integerPixel = int(finalValue + 0.5f); 977a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com *outPixel = SkClampMax( SkClampPos(integerPixel), 255 ); 978a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 979a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 980d454ec135eeef48edea7ebc47a61ff39bd654576skia.committer@gmail.com 981a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fImage = dstPixels; 982a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // if need be, alloc the "real" dst (same size as src) and copy/merge 983a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // the blur into it (applying the src) 984a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (style == kInner_Style) { 985a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com // now we allocate the "real" dst, mirror the size of src 986a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com size_t srcSize = src.computeImageSize(); 987a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (0 == srcSize) { 988a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com return false; // too big to allocate, abort 989a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 990a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fImage = SkMask::AllocImage(srcSize); 991a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com merge_src_with_blur(dst->fImage, src.fRowBytes, 992a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com srcPixels, src.fRowBytes, 993a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dstPixels + pad*dst->fRowBytes + pad, 994a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fRowBytes, srcWidth, srcHeight); 995a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com SkMask::FreeImage(dstPixels); 996a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } else if (style != kNormal_Style) { 997a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com clamp_with_orig(dstPixels + pad*dst->fRowBytes + pad, 998a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fRowBytes, srcPixels, src.fRowBytes, srcWidth, srcHeight, style); 9997c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 1000a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com (void)autoCall.detach(); 1001a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com } 1002a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com 1003a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com if (style == kInner_Style) { 1004a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fBounds = src.fBounds; // restore trimmed bounds 1005a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7humper@google.com dst->fRowBytes = src.fRowBytes; 10067c7292c6071898d73dc935c3b66b9816183806f0humper@google.com } 10078ae714b186ae5f4eaddee239281fbfe7282320c9skia.committer@gmail.com 10087c7292c6071898d73dc935c3b66b9816183806f0humper@google.com return true; 10097c7292c6071898d73dc935c3b66b9816183806f0humper@google.com} 1010