Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkMath.h"
     10 
     11 
     12 #define SCALE_NOFILTER_NAME     MAKENAME(_nofilter_scale)
     13 #define SCALE_FILTER_NAME       MAKENAME(_filter_scale)
     14 #define AFFINE_NOFILTER_NAME    MAKENAME(_nofilter_affine)
     15 #define AFFINE_FILTER_NAME      MAKENAME(_filter_affine)
     16 #define PERSP_NOFILTER_NAME     MAKENAME(_nofilter_persp)
     17 #define PERSP_FILTER_NAME       MAKENAME(_filter_persp)
     18 
     19 #define PACK_FILTER_X_NAME  MAKENAME(_pack_filter_x)
     20 #define PACK_FILTER_Y_NAME  MAKENAME(_pack_filter_y)
     21 
     22 #ifndef PREAMBLE
     23     #define PREAMBLE(state)
     24     #define PREAMBLE_PARAM_X
     25     #define PREAMBLE_PARAM_Y
     26     #define PREAMBLE_ARG_X
     27     #define PREAMBLE_ARG_Y
     28 #endif
     29 
     30 void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
     31                                 uint32_t xy[], int count, int x, int y) {
     32     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
     33                              SkMatrix::kScale_Mask)) == 0);
     34 
     35     PREAMBLE(s);
     36     // we store y, x, x, x, x, x
     37 
     38     const unsigned maxX = s.fBitmap->width() - 1;
     39     SkFixed fx;
     40     {
     41         SkPoint pt;
     42         s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
     43                                   SkIntToScalar(y) + SK_ScalarHalf, &pt);
     44         fx = SkScalarToFixed(pt.fY);
     45         const unsigned maxY = s.fBitmap->height() - 1;
     46         *xy++ = TILEY_PROCF(fx, maxY);
     47         fx = SkScalarToFixed(pt.fX);
     48     }
     49 
     50     if (0 == maxX) {
     51         // all of the following X values must be 0
     52         memset(xy, 0, count * sizeof(uint16_t));
     53         return;
     54     }
     55 
     56     const SkFixed dx = s.fInvSx;
     57 
     58 #ifdef CHECK_FOR_DECAL
     59     // test if we don't need to apply the tile proc
     60     if ((unsigned)(fx >> 16) <= maxX &&
     61         (unsigned)((fx + dx * (count - 1)) >> 16) <= maxX) {
     62         decal_nofilter_scale(xy, fx, dx, count);
     63     } else
     64 #endif
     65     {
     66         int i;
     67         for (i = (count >> 2); i > 0; --i) {
     68             unsigned a, b;
     69             a = TILEX_PROCF(fx, maxX); fx += dx;
     70             b = TILEX_PROCF(fx, maxX); fx += dx;
     71 #ifdef SK_CPU_BENDIAN
     72             *xy++ = (a << 16) | b;
     73 #else
     74             *xy++ = (b << 16) | a;
     75 #endif
     76             a = TILEX_PROCF(fx, maxX); fx += dx;
     77             b = TILEX_PROCF(fx, maxX); fx += dx;
     78 #ifdef SK_CPU_BENDIAN
     79             *xy++ = (a << 16) | b;
     80 #else
     81             *xy++ = (b << 16) | a;
     82 #endif
     83         }
     84         uint16_t* xx = (uint16_t*)xy;
     85         for (i = (count & 3); i > 0; --i) {
     86             *xx++ = TILEX_PROCF(fx, maxX); fx += dx;
     87         }
     88     }
     89 }
     90 
     91 // note: we could special-case on a matrix which is skewed in X but not Y.
     92 // this would require a more general setup thatn SCALE does, but could use
     93 // SCALE's inner loop that only looks at dx
     94 
     95 void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
     96                                  uint32_t xy[], int count, int x, int y) {
     97     SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
     98     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
     99                              SkMatrix::kScale_Mask |
    100                              SkMatrix::kAffine_Mask)) == 0);
    101 
    102     PREAMBLE(s);
    103     SkPoint srcPt;
    104     s.fInvProc(*s.fInvMatrix,
    105                SkIntToScalar(x) + SK_ScalarHalf,
    106                SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
    107 
    108     SkFixed fx = SkScalarToFixed(srcPt.fX);
    109     SkFixed fy = SkScalarToFixed(srcPt.fY);
    110     SkFixed dx = s.fInvSx;
    111     SkFixed dy = s.fInvKy;
    112     int maxX = s.fBitmap->width() - 1;
    113     int maxY = s.fBitmap->height() - 1;
    114 
    115     for (int i = count; i > 0; --i) {
    116         *xy++ = (TILEY_PROCF(fy, maxY) << 16) | TILEX_PROCF(fx, maxX);
    117         fx += dx; fy += dy;
    118     }
    119 }
    120 
    121 void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
    122                                 uint32_t* SK_RESTRICT xy,
    123                                 int count, int x, int y) {
    124     SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
    125 
    126     PREAMBLE(s);
    127     int maxX = s.fBitmap->width() - 1;
    128     int maxY = s.fBitmap->height() - 1;
    129 
    130     SkPerspIter   iter(*s.fInvMatrix,
    131                        SkIntToScalar(x) + SK_ScalarHalf,
    132                        SkIntToScalar(y) + SK_ScalarHalf, count);
    133 
    134     while ((count = iter.next()) != 0) {
    135         const SkFixed* SK_RESTRICT srcXY = iter.getXY();
    136         while (--count >= 0) {
    137             *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
    138                      TILEX_PROCF(srcXY[0], maxX);
    139             srcXY += 2;
    140         }
    141     }
    142 }
    143 
    144 //////////////////////////////////////////////////////////////////////////////
    145 
    146 static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
    147                                           SkFixed one PREAMBLE_PARAM_Y) {
    148     unsigned i = TILEY_PROCF(f, max);
    149     i = (i << 4) | TILEY_LOW_BITS(f, max);
    150     return (i << 14) | (TILEY_PROCF((f + one), max));
    151 }
    152 
    153 static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
    154                                           SkFixed one PREAMBLE_PARAM_X) {
    155     unsigned i = TILEX_PROCF(f, max);
    156     i = (i << 4) | TILEX_LOW_BITS(f, max);
    157     return (i << 14) | (TILEX_PROCF((f + one), max));
    158 }
    159 
    160 void SCALE_FILTER_NAME(const SkBitmapProcState& s,
    161                               uint32_t xy[], int count, int x, int y) {
    162     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
    163                              SkMatrix::kScale_Mask)) == 0);
    164     SkASSERT(s.fInvKy == 0);
    165 
    166     PREAMBLE(s);
    167 
    168     const unsigned maxX = s.fBitmap->width() - 1;
    169     const SkFixed one = s.fFilterOneX;
    170     const SkFixed dx = s.fInvSx;
    171     SkFixed fx;
    172 
    173     {
    174         SkPoint pt;
    175         s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
    176                                   SkIntToScalar(y) + SK_ScalarHalf, &pt);
    177         const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
    178         const unsigned maxY = s.fBitmap->height() - 1;
    179         // compute our two Y values up front
    180         *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
    181         // now initialize fx
    182         fx = SkScalarToFixed(pt.fX) - (one >> 1);
    183     }
    184 
    185 #ifdef CHECK_FOR_DECAL
    186     // test if we don't need to apply the tile proc
    187     if (dx > 0 &&
    188             (unsigned)(fx >> 16) <= maxX &&
    189             (unsigned)((fx + dx * (count - 1)) >> 16) < maxX) {
    190         decal_filter_scale(xy, fx, dx, count);
    191     } else
    192 #endif
    193     {
    194         do {
    195             *xy++ = PACK_FILTER_X_NAME(fx, maxX, one PREAMBLE_ARG_X);
    196             fx += dx;
    197         } while (--count != 0);
    198     }
    199 }
    200 
    201 void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
    202                                uint32_t xy[], int count, int x, int y) {
    203     SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
    204     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
    205                              SkMatrix::kScale_Mask |
    206                              SkMatrix::kAffine_Mask)) == 0);
    207 
    208     PREAMBLE(s);
    209     SkPoint srcPt;
    210     s.fInvProc(*s.fInvMatrix,
    211                SkIntToScalar(x) + SK_ScalarHalf,
    212                SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
    213 
    214     SkFixed oneX = s.fFilterOneX;
    215     SkFixed oneY = s.fFilterOneY;
    216     SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
    217     SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
    218     SkFixed dx = s.fInvSx;
    219     SkFixed dy = s.fInvKy;
    220     unsigned maxX = s.fBitmap->width() - 1;
    221     unsigned maxY = s.fBitmap->height() - 1;
    222 
    223     do {
    224         *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
    225         fy += dy;
    226         *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
    227         fx += dx;
    228     } while (--count != 0);
    229 }
    230 
    231 void PERSP_FILTER_NAME(const SkBitmapProcState& s,
    232                               uint32_t* SK_RESTRICT xy, int count,
    233                               int x, int y) {
    234     SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
    235 
    236     PREAMBLE(s);
    237     unsigned maxX = s.fBitmap->width() - 1;
    238     unsigned maxY = s.fBitmap->height() - 1;
    239     SkFixed oneX = s.fFilterOneX;
    240     SkFixed oneY = s.fFilterOneY;
    241 
    242     SkPerspIter   iter(*s.fInvMatrix,
    243                        SkIntToScalar(x) + SK_ScalarHalf,
    244                        SkIntToScalar(y) + SK_ScalarHalf, count);
    245 
    246     while ((count = iter.next()) != 0) {
    247         const SkFixed* SK_RESTRICT srcXY = iter.getXY();
    248         do {
    249             *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
    250                                        oneY PREAMBLE_ARG_Y);
    251             *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
    252                                        oneX PREAMBLE_ARG_X);
    253             srcXY += 2;
    254         } while (--count != 0);
    255     }
    256 }
    257 
    258 static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
    259     SCALE_NOFILTER_NAME,
    260     SCALE_FILTER_NAME,
    261     AFFINE_NOFILTER_NAME,
    262     AFFINE_FILTER_NAME,
    263     PERSP_NOFILTER_NAME,
    264     PERSP_FILTER_NAME
    265 };
    266 
    267 #undef MAKENAME
    268 #undef TILEX_PROCF
    269 #undef TILEY_PROCF
    270 #ifdef CHECK_FOR_DECAL
    271     #undef CHECK_FOR_DECAL
    272 #endif
    273 
    274 #undef SCALE_NOFILTER_NAME
    275 #undef SCALE_FILTER_NAME
    276 #undef AFFINE_NOFILTER_NAME
    277 #undef AFFINE_FILTER_NAME
    278 #undef PERSP_NOFILTER_NAME
    279 #undef PERSP_FILTER_NAME
    280 
    281 #undef PREAMBLE
    282 #undef PREAMBLE_PARAM_X
    283 #undef PREAMBLE_PARAM_Y
    284 #undef PREAMBLE_ARG_X
    285 #undef PREAMBLE_ARG_Y
    286 
    287 #undef TILEX_LOW_BITS
    288 #undef TILEY_LOW_BITS
    289