SkBlurMask.cpp revision 01224d5d0a3228fe47e63d8346e0e433a87563a8
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
1501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com// Unrolling the integer blur kernel seems to give us a ~15% speedup on Windows,
1601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com// breakeven on Mac, and ~15% slowdown on Linux.
1701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com// Reading a word at a time when bulding the sum buffer seems to give
1801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com// us no appreciable speedup on Windows or Mac, and 2% slowdown on Linux.
1901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#if defined(BUILD_FOR_WIN_32)
2001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#define UNROLL_KERNEL_LOOP 1
2101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#endif
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
234560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com/** The sum buffer is an array of u32 to hold the accumulated sum of all of the
244560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    src values at their position, plus all values above and to the left.
254560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    When we sample into this buffer, we need an initial row and column of 0s,
264560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    so we have an index correspondence as follows:
274560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com
284560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    src[i, j] == sum[i+1, j+1]
294560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    sum[0, j] == sum[i, 0] == 0
304560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com
314560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    We assume that the sum buffer's stride == its width
324560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com */
3303016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.comstatic void build_sum_buffer(uint32_t sum[], int srcW, int srcH,
3403016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                             const uint8_t src[], int srcRB) {
354560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int sumW = srcW + 1;
364560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com
374560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    SkASSERT(srcRB >= srcW);
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // mod srcRB so we can apply it after each row
394560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    srcRB -= srcW;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x, y;
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
434560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    // zero out the top row and column
444560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    memset(sum, 0, sumW * sizeof(sum[0]));
454560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    sum += sumW;
464560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // special case first row
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t X = 0;
494560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    *sum++ = 0; // initialze the first column to 0
5003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com    for (x = srcW - 1; x >= 0; --x) {
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        X = *src++ + X;
524560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        *sum++ = X;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    src += srcRB;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the rest of the rows
5703016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com    for (y = srcH - 1; y > 0; --y) {
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t L = 0;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t C = 0;
604560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        *sum++ = 0; // initialze the first column to 0
6101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
6201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (x = srcW - 1; !SkIsAlign4((intptr_t) src) && x >= 0; x--) {
6301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t T = sum[-sumW];
6401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            X = *src++ + L + T - C;
6501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *sum++ = X;
6601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            L = X;
6701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            C = T;
6801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        }
6901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
7001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (; x >= 4; x-=4) {
7101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t T = sum[-sumW];
7201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            X = *src++ + L + T - C;
7301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *sum++ = X;
7401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            L = X;
7501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            C = T;
7601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            T = sum[-sumW];
7701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            X = *src++ + L + T - C;
7801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *sum++ = X;
7901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            L = X;
8001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            C = T;
8101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            T = sum[-sumW];
8201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            X = *src++ + L + T - C;
8301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *sum++ = X;
8401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            L = X;
8501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            C = T;
8601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            T = sum[-sumW];
8701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            X = *src++ + L + T - C;
8801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *sum++ = X;
8901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            L = X;
9001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            C = T;
9101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        }
9201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
9301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (; x >= 0; --x) {
944560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com            uint32_t T = sum[-sumW];
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            X = *src++ + L + T - C;
964560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com            *sum++ = X;
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            L = X;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            C = T;
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += srcRB;
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10403016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com/**
1058caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com * This is the path for apply_kernel() to be taken when the kernel
1068caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com * is wider than the source image.
1078caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com */
1088caac6447dd68655b57dfe876626a9733b191416tomhudson@google.comstatic void kernel_clamped(uint8_t dst[], int rx, int ry, const uint32_t sum[],
1098caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                           int sw, int sh) {
1108caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    SkASSERT(2*rx > sw);
1118caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1128caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    uint32_t scale = (1 << 24) / ((2*rx + 1)*(2*ry + 1));
1138caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1148caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int sumStride = sw + 1;
1158caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1168caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int dw = sw + 2*rx;
1178caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int dh = sh + 2*ry;
1188caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1198caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int prev_y = -2*ry;
1208caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int next_y = 1;
1218caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1228caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    for (int y = 0; y < dh; y++) {
1238caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int py = SkClampPos(prev_y) * sumStride;
1248caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int ny = SkFastMin32(next_y, sh) * sumStride;
1258caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1268caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int prev_x = -2*rx;
1278caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int next_x = 1;
1288caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1298caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (int x = 0; x < dw; x++) {
1308caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = SkClampPos(prev_x);
1318caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = SkFastMin32(next_x, sw);
1328caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1338caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t tmp = sum[px+py] + sum[nx+ny] - sum[nx+py] - sum[px+ny];
1348caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
1358caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1368caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
1378caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
1388caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
1398caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1408caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        prev_y += 1;
1418caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        next_y += 1;
1428caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    }
1438caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com}
1448caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com/**
14503016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  sw and sh are the width and height of the src. Since the sum buffer
14603016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  matches that, but has an extra row and col at the beginning (with zeros),
14703016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  we can just use sw and sh as our "max" values for pinning coordinates
14803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  when sampling into sum[][]
1498caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com *
1508caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com *  The inner loop is conceptually simple; we break it into several sections
1518caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com *  to improve performance. Here's the original version:
1528caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (int x = 0; x < dw; x++) {
1538caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = SkClampPos(prev_x);
1548caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = SkFastMin32(next_x, sw);
1558caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1568caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t tmp = sum[px+py] + sum[nx+ny] - sum[nx+py] - sum[px+ny];
1578caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
1588caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1598caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
1608caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
1618caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
16201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *  The sections are:
16301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *     left-hand section, where prev_x is clamped to 0
16401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *     center section, where neither prev_x nor next_x is clamped
16501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *     right-hand section, where next_x is clamped to sw
16601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *  On some operating systems, the center section is unrolled for additional
16701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *  speedup.
1688caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com*/
1694560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.comstatic void apply_kernel(uint8_t dst[], int rx, int ry, const uint32_t sum[],
1704560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com                         int sw, int sh) {
1718caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    if (2*rx > sw) {
1728caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        kernel_clamped(dst, rx, ry, sum, sw, sh);
1738caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        return;
1748caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    }
1758caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t scale = (1 << 24) / ((2*rx + 1)*(2*ry + 1));
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1784560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int sumStride = sw + 1;
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dw = sw + 2*rx;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dh = sh + 2*ry;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1834560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int prev_y = -2*ry;
1844560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int next_y = 1;
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1868caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    SkASSERT(2*rx <= dw - 2*rx);
1878caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1884560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    for (int y = 0; y < dh; y++) {
1894560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int py = SkClampPos(prev_y) * sumStride;
1904560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int ny = SkFastMin32(next_y, sh) * sumStride;
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1924560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int prev_x = -2*rx;
1934560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int next_x = 1;
1948caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int x = 0;
1958caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
1968caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (; x < 2*rx; x++) {
1978caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(prev_x <= 0);
1988caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(next_x <= sw);
1998caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2008caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = 0;
2018caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = next_x;
2028caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2038caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t tmp = sum[px+py] + sum[nx+ny] - sum[nx+py] - sum[px+ny];
2048caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
2058caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2068caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
2078caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
2088caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
2098caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
21001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i0 = prev_x + py;
21101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i1 = next_x + ny;
21201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i2 = next_x + py;
21301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i3 = prev_x + ny;
21401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
21501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#if UNROLL_KERNEL_LOOP
21601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (; x < dw - 2*rx - 4; x += 4) {
2178caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(prev_x >= 0);
2188caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(next_x <= sw);
2198caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
22001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t tmp = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
22101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
22201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            tmp = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
22301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
22401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            tmp = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
22501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
22601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            tmp = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
22701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
2288caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
22901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            prev_x += 4;
23001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            next_x += 4;
23101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        }
23201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#endif
23301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
23401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (; x < dw - 2*rx; x++) {
23501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            SkASSERT(prev_x >= 0);
23601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            SkASSERT(next_x <= sw);
23701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
23801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t tmp = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
2398caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
2408caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2418caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
2428caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
2438caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
2448caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2458caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (; x < dw; x++) {
2468caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(prev_x >= 0);
2478caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(next_x > sw);
2488caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2498caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = prev_x;
2508caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = sw;
2518caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2528caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t tmp = sum[px+py] + sum[nx+ny] - sum[nx+py] - sum[px+ny];
2538caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8(tmp * scale >> 24);
2548caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2558caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
2568caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
2578caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
2588caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2598caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        prev_y += 1;
2608caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        next_y += 1;
2618caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    }
2628caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com}
2638caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2648caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com/**
2658caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com * This is the path for apply_kernel_interp() to be taken when the kernel
2668caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com * is wider than the source image.
2678caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com */
2688caac6447dd68655b57dfe876626a9733b191416tomhudson@google.comstatic void kernel_interp_clamped(uint8_t dst[], int rx, int ry,
2698caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                const uint32_t sum[], int sw, int sh, U8CPU outer_weight) {
2708caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    SkASSERT(2*rx > sw);
2718caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2728caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int inner_weight = 255 - outer_weight;
2738caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2748caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    // round these guys up if they're bigger than 127
2758caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    outer_weight += outer_weight >> 7;
2768caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    inner_weight += inner_weight >> 7;
2778caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2788caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    uint32_t outer_scale = (outer_weight << 16) / ((2*rx + 1)*(2*ry + 1));
2798caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    uint32_t inner_scale = (inner_weight << 16) / ((2*rx - 1)*(2*ry - 1));
2808caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2818caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int sumStride = sw + 1;
2828caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2838caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int dw = sw + 2*rx;
2848caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int dh = sh + 2*ry;
2858caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2868caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int prev_y = -2*ry;
2878caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    int next_y = 1;
2888caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2898caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    for (int y = 0; y < dh; y++) {
2908caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int py = SkClampPos(prev_y) * sumStride;
2918caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int ny = SkFastMin32(next_y, sh) * sumStride;
2928caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2938caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int ipy = SkClampPos(prev_y + 1) * sumStride;
2948caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int iny = SkClampMax(next_y - 1, sh) * sumStride;
2958caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
2968caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int prev_x = -2*rx;
2978caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int next_x = 1;
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2994560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        for (int x = 0; x < dw; x++) {
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int px = SkClampPos(prev_x);
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int nx = SkFastMin32(next_x, sw);
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3038caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int ipx = SkClampPos(prev_x + 1);
3048caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int inx = SkClampMax(next_x - 1, sw);
3058caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
3068caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t outer_sum = sum[px+py] + sum[nx+ny]
3078caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[nx+py] - sum[px+ny];
3088caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t inner_sum = sum[ipx+ipy] + sum[inx+iny]
3098caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[inx+ipy] - sum[ipx+iny];
3108caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
3118caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            prev_x += 1;
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            next_x += 1;
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prev_y += 1;
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        next_y += 1;
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32103016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com/**
32203016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  sw and sh are the width and height of the src. Since the sum buffer
32303016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  matches that, but has an extra row and col at the beginning (with zeros),
32403016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  we can just use sw and sh as our "max" values for pinning coordinates
32503016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com *  when sampling into sum[][]
3268caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com *
3278caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com *  The inner loop is conceptually simple; we break it into several variants
3288caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com *  to improve performance. Here's the original version:
3298caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (int x = 0; x < dw; x++) {
3308caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = SkClampPos(prev_x);
3318caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = SkFastMin32(next_x, sw);
3328caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
3338caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int ipx = SkClampPos(prev_x + 1);
3348caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int inx = SkClampMax(next_x - 1, sw);
3358caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
3368caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t outer_sum = sum[px+py] + sum[nx+ny]
3378caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[nx+py] - sum[px+ny];
3388caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t inner_sum = sum[ipx+ipy] + sum[inx+iny]
3398caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[inx+ipy] - sum[ipx+iny];
3408caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
3418caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
3428caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
3438caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
3448caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
3458caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
34601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *  The sections are:
34701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *     left-hand section, where prev_x is clamped to 0
34801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *     center section, where neither prev_x nor next_x is clamped
34901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *     right-hand section, where next_x is clamped to sw
35001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *  On some operating systems, the center section is unrolled for additional
35101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com *  speedup.
3528caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com*/
3534560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.comstatic void apply_kernel_interp(uint8_t dst[], int rx, int ry,
3544560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com                const uint32_t sum[], int sw, int sh, U8CPU outer_weight) {
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rx > 0 && ry > 0);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(outer_weight <= 255);
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3588caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    if (2*rx > sw) {
3598caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        kernel_interp_clamped(dst, rx, ry, sum, sw, sh, outer_weight);
3608caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        return;
3618caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    }
3628caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int inner_weight = 255 - outer_weight;
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // round these guys up if they're bigger than 127
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    outer_weight += outer_weight >> 7;
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inner_weight += inner_weight >> 7;
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t outer_scale = (outer_weight << 16) / ((2*rx + 1)*(2*ry + 1));
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t inner_scale = (inner_weight << 16) / ((2*rx - 1)*(2*ry - 1));
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3724560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int sumStride = sw + 1;
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dw = sw + 2*rx;
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dh = sh + 2*ry;
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3774560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int prev_y = -2*ry;
3784560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    int next_y = 1;
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3808caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com    SkASSERT(2*rx <= dw - 2*rx);
3818caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
3824560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com    for (int y = 0; y < dh; y++) {
3834560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int py = SkClampPos(prev_y) * sumStride;
3844560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int ny = SkFastMin32(next_y, sh) * sumStride;
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3864560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int ipy = SkClampPos(prev_y + 1) * sumStride;
3874560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int iny = SkClampMax(next_y - 1, sh) * sumStride;
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3894560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int prev_x = -2*rx;
3904560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com        int next_x = 1;
3918caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        int x = 0;
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3938caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (; x < 2*rx; x++) {
3948caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(prev_x < 0);
3958caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(next_x <= sw);
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3978caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = 0;
3988caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = next_x;
3998caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4008caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int ipx = 0;
4018caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int inx = next_x - 1;
4028caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4038caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t outer_sum = sum[px+py] + sum[nx+ny]
4048caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[nx+py] - sum[px+ny];
4058caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t inner_sum = sum[ipx+ipy] + sum[inx+iny]
4068caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[inx+ipy] - sum[ipx+iny];
4078caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
4088caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
4098caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4108caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
4118caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
4128caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
4138caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
41401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i0 = prev_x + py;
41501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i1 = next_x + ny;
41601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i2 = next_x + py;
41701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i3 = prev_x + ny;
41801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i4 = prev_x + 1 + ipy;
41901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i5 = next_x - 1 + iny;
42001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i6 = next_x - 1 + ipy;
42101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        int i7 = prev_x + 1 + iny;
42201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
42301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#if UNROLL_KERNEL_LOOP
42401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (; x < dw - 2*rx - 4; x += 4) {
4258caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(prev_x >= 0);
4268caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(next_x <= sw);
4278caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
42801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t outer_sum = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
42901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t inner_sum = sum[i4++] + sum[i5++] - sum[i6++] - sum[i7++];
43001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
43101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
43201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            outer_sum = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
43301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            inner_sum = sum[i4++] + sum[i5++] - sum[i6++] - sum[i7++];
43401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
43501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
43601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            outer_sum = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
43701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            inner_sum = sum[i4++] + sum[i5++] - sum[i6++] - sum[i7++];
43801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
43901224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
44001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            outer_sum = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
44101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            inner_sum = sum[i4++] + sum[i5++] - sum[i6++] - sum[i7++];
44201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
44301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
4448caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
44501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            prev_x += 4;
44601224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            next_x += 4;
44701224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        }
44801224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com#endif
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45001224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com        for (; x < dw - 2*rx; x++) {
45101224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            SkASSERT(prev_x >= 0);
45201224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            SkASSERT(next_x <= sw);
45301224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com
45401224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t outer_sum = sum[i0++] + sum[i1++] - sum[i2++] - sum[i3++];
45501224d5d0a3228fe47e63d8346e0e433a87563a8tomhudson@google.com            uint32_t inner_sum = sum[i4++] + sum[i5++] - sum[i6++] - sum[i7++];
4568caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
4578caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            prev_x += 1;
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            next_x += 1;
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4628caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4638caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        for (; x < dw; x++) {
4648caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(prev_x >= 0);
4658caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            SkASSERT(next_x > sw);
4668caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4678caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int px = prev_x;
4688caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int nx = sw;
4698caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4708caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int ipx = prev_x + 1;
4718caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            int inx = sw;
4728caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4738caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t outer_sum = sum[px+py] + sum[nx+ny]
4748caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[nx+py] - sum[px+ny];
4758caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            uint32_t inner_sum = sum[ipx+ipy] + sum[inx+iny]
4768caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                               - sum[inx+ipy] - sum[ipx+iny];
4778caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            *dst++ = SkToU8((outer_sum * outer_scale
4788caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com                           + inner_sum * inner_scale) >> 24);
4798caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4808caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            prev_x += 1;
4818caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com            next_x += 1;
4828caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com        }
4838caac6447dd68655b57dfe876626a9733b191416tomhudson@google.com
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prev_y += 1;
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        next_y += 1;
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4910e3c664250f561ec9f7107b92136517a72d03afdreed@android.comstatic void merge_src_with_blur(uint8_t dst[], int dstRB,
4920e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                                const uint8_t src[], int srcRB,
4930e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                                const uint8_t blur[], int blurRB,
4940e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                                int sw, int sh) {
4950e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    dstRB -= sw;
4960e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    srcRB -= sw;
4970e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    blurRB -= sw;
4980e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    while (--sh >= 0) {
4990e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        for (int x = sw - 1; x >= 0; --x) {
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst = SkToU8(SkAlphaMul(*blur, SkAlpha255To256(*src)));
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst += 1;
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src += 1;
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blur += 1;
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5050e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        dst += dstRB;
5060e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        src += srcRB;
5070e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        blur += blurRB;
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void clamp_with_orig(uint8_t dst[], int dstRowBytes,
5120e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                            const uint8_t src[], int srcRowBytes,
5130e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                            int sw, int sh,
5144560767bb0b3db530d48e2b0c1c11e28f3692984reed@android.com                            SkBlurMask::Style style) {
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x;
5160e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    while (--sh >= 0) {
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        switch (style) {
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBlurMask::kSolid_Style:
5190e3c664250f561ec9f7107b92136517a72d03afdreed@android.com            for (x = sw - 1; x >= 0; --x) {
5200e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                int s = *src;
5210e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                int d = *dst;
5220e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                *dst = SkToU8(s + d - SkMulDiv255Round(s, d));
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                dst += 1;
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                src += 1;
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkBlurMask::kOuter_Style:
5280e3c664250f561ec9f7107b92136517a72d03afdreed@android.com            for (x = sw - 1; x >= 0; --x) {
5290e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                if (*src) {
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src)));
5310e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                }
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                dst += 1;
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                src += 1;
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(!"Unexpected blur style here");
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst += dstRowBytes - sw;
5410e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        src += srcRowBytes - sw;
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54503016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com///////////////////////////////////////////////////////////////////////////////
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// we use a local funciton to wrap the class static method to work around
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// a bug in gcc98
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMask_FreeImage(uint8_t* image);
55003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.comvoid SkMask_FreeImage(uint8_t* image) {
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMask::FreeImage(image);
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
5555af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com                      SkScalar radius, Style style, Quality quality,
5565af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com                      SkIPoint* margin)
5575af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com{
55803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com    if (src.fFormat != SkMask::kA8_Format) {
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
56003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com    }
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5624868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    // Force high quality off for small radii (performance)
5634868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    if (radius < SkIntToScalar(3)) quality = kLow_Quality;
5644868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
5654868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    // highQuality: use three box blur passes as a cheap way to approximate a Gaussian blur
5664868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    int passCount = (quality == kHigh_Quality) ? 3 : 1;
5674868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    SkScalar passRadius = SkScalarDiv(radius, SkScalarSqrt(SkIntToScalar(passCount)));
5684868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
5694868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    int rx = SkScalarCeil(passRadius);
5704868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    int outer_weight = 255 - SkScalarRound((SkIntToScalar(rx) - passRadius) * 255);
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rx >= 0);
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)outer_weight <= 255);
5740e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    if (rx <= 0) {
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
5760e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    }
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int ry = rx;    // only do square blur for now
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5804868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    int padx = passCount * rx;
5814868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    int pady = passCount * ry;
5825af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com    if (margin) {
5835af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com        margin->set(padx, pady);
5845af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com    }
5854868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org    dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady,
5864868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org        src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
58749f0ff25a046d6001dc2d095b6fa3c30f0f46b6areed@android.com    dst->fRowBytes = dst->fBounds.width();
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dst->fFormat = SkMask::kA8_Format;
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dst->fImage = NULL;
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5910e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    if (src.fImage) {
592543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        size_t dstSize = dst->computeImageSize();
593543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        if (0 == dstSize) {
594543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com            return false;   // too big to allocate, abort
595543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        }
596543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int             sw = src.fBounds.width();
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int             sh = src.fBounds.height();
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  sp = src.fImage;
600543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        uint8_t*        dp = SkMask::AllocImage(dstSize);
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp);
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // build the blurry destination
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
60603016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            const size_t storageW = sw + 2 * (passCount - 1) * rx + 1;
60703016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            const size_t storageH = sh + 2 * (passCount - 1) * ry + 1;
60803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            SkAutoTMalloc<uint32_t> storage(storageW * storageH);
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint32_t*               sumBuffer = storage.get();
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6114868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            //pass1: sp is source, dp is destination
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            build_sum_buffer(sumBuffer, sw, sh, sp, src.fRowBytes);
61303016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            if (outer_weight == 255) {
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                apply_kernel(dp, rx, ry, sumBuffer, sw, sh);
61503016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            } else {
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                apply_kernel_interp(dp, rx, ry, sumBuffer, sw, sh, outer_weight);
61703016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            }
6184868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
61903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            if (quality == kHigh_Quality) {
6204868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                //pass2: dp is source, tmpBuffer is destination
6214868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                int tmp_sw = sw + 2 * rx;
6224868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                int tmp_sh = sh + 2 * ry;
6234868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                SkAutoTMalloc<uint8_t>  tmpBuffer(dstSize);
6244868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                build_sum_buffer(sumBuffer, tmp_sw, tmp_sh, dp, tmp_sw);
6254868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                if (outer_weight == 255)
6264868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                    apply_kernel(tmpBuffer.get(), rx, ry, sumBuffer, tmp_sw, tmp_sh);
6274868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                else
62803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                    apply_kernel_interp(tmpBuffer.get(), rx, ry, sumBuffer,
62903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                                        tmp_sw, tmp_sh, outer_weight);
6304868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org
6314868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                //pass3: tmpBuffer is source, dp is destination
6324868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                tmp_sw += 2 * rx;
6334868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                tmp_sh += 2 * ry;
6344868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                build_sum_buffer(sumBuffer, tmp_sw, tmp_sh, tmpBuffer.get(), tmp_sw);
6354868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                if (outer_weight == 255)
6364868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                    apply_kernel(dp, rx, ry, sumBuffer, tmp_sw, tmp_sh);
6374868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org                else
63803016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                    apply_kernel_interp(dp, rx, ry, sumBuffer, tmp_sw, tmp_sh,
63903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                                        outer_weight);
6404868e6b221a4a98e40f977851af5fcf09631ea15senorblanco@chromium.org            }
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst->fImage = dp;
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // if need be, alloc the "real" dst (same size as src) and copy/merge
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // the blur into it (applying the src)
6460e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        if (style == kInner_Style) {
6470e3c664250f561ec9f7107b92136517a72d03afdreed@android.com            // now we allocate the "real" dst, mirror the size of src
648543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com            size_t srcSize = src.computeImageSize();
649543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com            if (0 == srcSize) {
650543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com                return false;   // too big to allocate, abort
651543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com            }
652543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com            dst->fImage = SkMask::AllocImage(srcSize);
6530e3c664250f561ec9f7107b92136517a72d03afdreed@android.com            merge_src_with_blur(dst->fImage, src.fRowBytes,
6540e3c664250f561ec9f7107b92136517a72d03afdreed@android.com                                sp, src.fRowBytes,
65503016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                                dp + passCount * (rx + ry * dst->fRowBytes),
65603016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                                dst->fRowBytes, sw, sh);
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkMask::FreeImage(dp);
6580e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        } else if (style != kNormal_Style) {
65903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com            clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes),
66003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com                            dst->fRowBytes, sp, src.fRowBytes, sw, sh, style);
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (void)autoCall.detach();
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6650e3c664250f561ec9f7107b92136517a72d03afdreed@android.com    if (style == kInner_Style) {
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst->fBounds = src.fBounds; // restore trimmed bounds
6670e3c664250f561ec9f7107b92136517a72d03afdreed@android.com        dst->fRowBytes = src.fRowBytes;
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
673