169d05551332e61e22da4bd3b61fc6d065b461d4areed@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
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.
769d05551332e61e22da4bd3b61fc6d065b461d4areed@google.com */
869d05551332e61e22da4bd3b61fc6d065b461d4areed@google.com
9889bd8bd7f604acae0a6303365bc82c06da1e6f3tomhudson@google.com#include "SkMath.h"
104b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SCALE_FILTER_NAME       MAKENAME(_filter_scale)
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define AFFINE_FILTER_NAME      MAKENAME(_filter_affine)
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define PERSP_FILTER_NAME       MAKENAME(_filter_persp)
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define PACK_FILTER_X_NAME  MAKENAME(_pack_filter_x)
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define PACK_FILTER_Y_NAME  MAKENAME(_pack_filter_y)
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef PREAMBLE
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define PREAMBLE(state)
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define PREAMBLE_PARAM_X
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define PREAMBLE_PARAM_Y
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define PREAMBLE_ARG_X
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define PREAMBLE_ARG_Y
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com// declare functions externally to suppress warnings.
28803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.comvoid SCALE_FILTER_NAME(const SkBitmapProcState& s,
29803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com                              uint32_t xy[], int count, int x, int y);
30803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.comvoid AFFINE_FILTER_NAME(const SkBitmapProcState& s,
31803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com                               uint32_t xy[], int count, int x, int y);
32803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.comvoid PERSP_FILTER_NAME(const SkBitmapProcState& s,
33803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com                              uint32_t* SK_RESTRICT xy, int count,
34803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com                              int x, int y);
35803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          SkFixed one PREAMBLE_PARAM_Y) {
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned i = TILEY_PROCF(f, max);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    i = (i << 4) | TILEY_LOW_BITS(f, max);
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (i << 14) | (TILEY_PROCF((f + one), max));
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          SkFixed one PREAMBLE_PARAM_X) {
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned i = TILEX_PROCF(f, max);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    i = (i << 4) | TILEX_LOW_BITS(f, max);
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (i << 14) | (TILEX_PROCF((f + one), max));
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50dc7de745dd142cdc00ffed7963ebb030a0506f72senorblanco@chromium.orgvoid SCALE_FILTER_NAME(const SkBitmapProcState& s,
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              uint32_t xy[], int count, int x, int y) {
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SkMatrix::kScale_Mask)) == 0);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(s.fInvKy == 0);
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    PREAMBLE(s);
57fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned maxX = s.fBitmap->width() - 1;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkFixed one = s.fFilterOneX;
60411215ae2b9a36ff6e262f77d7fb5071cc084f00reed@google.com    const SkFractionalInt dx = s.fInvSxFractionalInt;
61411215ae2b9a36ff6e262f77d7fb5071cc084f00reed@google.com    SkFractionalInt fx;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint pt;
659c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com        s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                  SkIntToScalar(y) + SK_ScalarHalf, &pt);
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const unsigned maxY = s.fBitmap->height() - 1;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // compute our two Y values up front
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now initialize fx
72411215ae2b9a36ff6e262f77d7fb5071cc084f00reed@google.com        fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef CHECK_FOR_DECAL
764d0078aa5115fab8ccd8ef59519a8937ea4e8854reed@google.com    if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
774d0078aa5115fab8ccd8ef59519a8937ea4e8854reed@google.com        decal_filter_scale(xy, SkFractionalIntToFixed(fx),
784d0078aa5115fab8ccd8ef59519a8937ea4e8854reed@google.com                           SkFractionalIntToFixed(dx), count);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
83411215ae2b9a36ff6e262f77d7fb5071cc084f00reed@google.com            SkFixed fixedFx = SkFractionalIntToFixed(fx);
84411215ae2b9a36ff6e262f77d7fb5071cc084f00reed@google.com            *xy++ = PACK_FILTER_X_NAME(fixedFx, maxX, one PREAMBLE_ARG_X);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fx += dx;
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90dc7de745dd142cdc00ffed7963ebb030a0506f72senorblanco@chromium.orgvoid AFFINE_FILTER_NAME(const SkBitmapProcState& s,
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               uint32_t xy[], int count, int x, int y) {
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SkMatrix::kScale_Mask |
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SkMatrix::kAffine_Mask)) == 0);
96fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    PREAMBLE(s);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint srcPt;
999c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com    s.fInvProc(s.fInvMatrix,
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               SkIntToScalar(x) + SK_ScalarHalf,
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed oneX = s.fFilterOneX;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed oneY = s.fFilterOneY;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed dx = s.fInvSx;
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed dy = s.fInvKy;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned maxX = s.fBitmap->width() - 1;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned maxY = s.fBitmap->height() - 1;
111fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fy += dy;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fx += dx;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count != 0);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
120dc7de745dd142cdc00ffed7963ebb030a0506f72senorblanco@chromium.orgvoid PERSP_FILTER_NAME(const SkBitmapProcState& s,
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              uint32_t* SK_RESTRICT xy, int count,
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              int x, int y) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
124fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    PREAMBLE(s);
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned maxX = s.fBitmap->width() - 1;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned maxY = s.fBitmap->height() - 1;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed oneX = s.fFilterOneX;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFixed oneY = s.fFilterOneY;
130fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1319c96d4b5ffdbf8c82f55b2058a2fea7225fe11d6humper@google.com    SkPerspIter   iter(s.fInvMatrix,
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkIntToScalar(x) + SK_ScalarHalf,
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkIntToScalar(y) + SK_ScalarHalf, count);
134fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while ((count = iter.next()) != 0) {
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkFixed* SK_RESTRICT srcXY = iter.getXY();
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       oneY PREAMBLE_ARG_Y);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       oneX PREAMBLE_ARG_X);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            srcXY += 2;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef MAKENAME
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef TILEX_PROCF
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef TILEY_PROCF
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef CHECK_FOR_DECAL
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #undef CHECK_FOR_DECAL
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef SCALE_FILTER_NAME
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef AFFINE_FILTER_NAME
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef PERSP_FILTER_NAME
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef PREAMBLE
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef PREAMBLE_PARAM_X
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef PREAMBLE_PARAM_Y
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef PREAMBLE_ARG_X
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef PREAMBLE_ARG_Y
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef TILEX_LOW_BITS
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#undef TILEY_LOW_BITS
166