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