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 class ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader {
     10 public:
     11     ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src)
     12         : SkBitmapShader(src, true,
     13                          SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)
     14     {}
     15 
     16     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
     17 };
     18 
     19 SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
     20                         const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table);
     21 SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
     22                         const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table)
     23 {
     24     int ix = fx >> 16;
     25     int iy = fy >> 16;
     26 
     27     const SkPMColor *p00, *p01, *p10, *p11;
     28 
     29     p00 = p01 = ((const SkPMColor*)((const char*)srcPixels
     30                                     + SkClampMax(iy, srcMaxY) * srcRB))
     31                                     + SkClampMax(ix, srcMaxX);
     32 
     33     if ((unsigned)ix < srcMaxX)
     34         p01 += 1;
     35     p10 = p00;
     36     p11 = p01;
     37     if ((unsigned)iy < srcMaxY)
     38     {
     39         p10 = (const SkPMColor*)((const char*)p10 + srcRB);
     40         p11 = (const SkPMColor*)((const char*)p11 + srcRB);
     41     }
     42 
     43     SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(proc_table, fx, fy);
     44     return proc(p00, p01, p10, p11);
     45 }
     46 
     47 static inline SkPMColor sample_bilerpx(SkFixed fx, unsigned srcMaxX, const SkPMColor* srcPixels,
     48                                        int srcRB, const SkFilterPtrProc* proc_table)
     49 {
     50     int ix = fx >> 16;
     51 
     52     const SkPMColor *p00, *p01, *p10, *p11;
     53 
     54     p00 = p01 = srcPixels + SkClampMax(ix, srcMaxX);
     55     if ((unsigned)ix < srcMaxX)
     56         p01 += 1;
     57 
     58     p10 = (const SkPMColor*)((const char*)p00 + srcRB);
     59     p11 = (const SkPMColor*)((const char*)p01 + srcRB);
     60 
     61     SkFilterPtrProc proc = SkGetBilinearFilterPtrXProc(proc_table, fx);
     62     return proc(p00, p01, p10, p11);
     63 }
     64 
     65 void ARGB32_Clamp_Bilinear_BitmapShader::shadeSpan(int x, int y, SkPMColor dstC[], int count)
     66 {
     67     SkASSERT(count > 0);
     68 
     69     unsigned srcScale = SkAlpha255To256(this->getPaintAlpha());
     70 
     71     const SkMatrix& inv = this->getTotalInverse();
     72     const SkBitmap& srcBitmap = this->getSrcBitmap();
     73     unsigned        srcMaxX = srcBitmap.width() - 1;
     74     unsigned        srcMaxY = srcBitmap.height() - 1;
     75     unsigned        srcRB = srcBitmap.rowBytes();
     76 
     77     const SkFilterPtrProc* proc_table = SkGetBilinearFilterPtrProcTable();
     78     const SkPMColor* srcPixels = (const SkPMColor*)srcBitmap.getPixels();
     79 
     80     if (this->getInverseClass() == kPerspective_MatrixClass)
     81     {
     82         SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
     83                                 SkIntToScalar(y) + SK_ScalarHalf, count);
     84 
     85         if (256 == srcScale)
     86         {
     87             while ((count = iter.next()) != 0)
     88             {
     89                 const SkFixed* srcXY = iter.getXY();
     90                 while (--count >= 0)
     91                 {
     92                     SkFixed fx = *srcXY++ - SK_FixedHalf;
     93                     SkFixed fy = *srcXY++ - SK_FixedHalf;
     94                     *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
     95                 }
     96             }
     97         }
     98         else    // scale by srcScale
     99         {
    100             while ((count = iter.next()) != 0)
    101             {
    102                 const SkFixed* srcXY = iter.getXY();
    103                 while (--count >= 0)
    104                 {
    105                     SkFixed fx = *srcXY++ - SK_FixedHalf;
    106                     SkFixed fy = *srcXY++ - SK_FixedHalf;
    107                     SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
    108                     *dstC++ = SkAlphaMulQ(c, srcScale);
    109                 }
    110             }
    111         }
    112     }
    113     else    // linear case
    114     {
    115         SkFixed fx, fy, dx, dy;
    116 
    117         // now init fx, fy, dx, dy
    118         {
    119             SkPoint srcPt;
    120             this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf,
    121                                              SkIntToScalar(y) + SK_ScalarHalf,
    122                                              &srcPt);
    123 
    124             fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf;
    125             fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf;
    126 
    127             if (this->getInverseClass() == kFixedStepInX_MatrixClass)
    128                 (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
    129             else
    130             {
    131                 dx = SkScalarToFixed(inv.getScaleX());
    132                 dy = SkScalarToFixed(inv.getSkewY());
    133             }
    134         }
    135 
    136         if (dy == 0 && (unsigned)(fy >> 16) < srcMaxY)
    137         {
    138             srcPixels = (const SkPMColor*)((const char*)srcPixels + (fy >> 16) * srcRB);
    139             proc_table = SkGetBilinearFilterPtrProcYTable(proc_table, fy);
    140             if (256 == srcScale)
    141             {
    142                 do {
    143                     *dstC++ = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
    144                     fx += dx;
    145                 } while (--count != 0);
    146             }
    147             else
    148             {
    149                 do {
    150                     SkPMColor c = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
    151                     *dstC++ = SkAlphaMulQ(c, srcScale);
    152                     fx += dx;
    153                 } while (--count != 0);
    154             }
    155         }
    156         else    // dy is != 0
    157         {
    158             if (256 == srcScale)
    159             {
    160                 do {
    161                     *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
    162                     fx += dx;
    163                     fy += dy;
    164                 } while (--count != 0);
    165             }
    166             else
    167             {
    168                 do {
    169                     SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
    170                     *dstC++ = SkAlphaMulQ(c, srcScale);
    171                     fx += dx;
    172                     fy += dy;
    173                 } while (--count != 0);
    174             }
    175         }
    176     }
    177 }
    178 
    179