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