10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader {
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src)
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        : SkBitmapShader(src, true,
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {}
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table);
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table)
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int ix = fx >> 16;
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int iy = fy >> 16;
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPMColor *p00, *p01, *p10, *p11;
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    p00 = p01 = ((const SkPMColor*)((const char*)srcPixels
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    + SkClampMax(iy, srcMaxY) * srcRB))
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    + SkClampMax(ix, srcMaxX);
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned)ix < srcMaxX)
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p01 += 1;
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    p10 = p00;
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    p11 = p01;
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned)iy < srcMaxY)
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p10 = (const SkPMColor*)((const char*)p10 + srcRB);
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p11 = (const SkPMColor*)((const char*)p11 + srcRB);
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(proc_table, fx, fy);
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return proc(p00, p01, p10, p11);
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkPMColor sample_bilerpx(SkFixed fx, unsigned srcMaxX, const SkPMColor* srcPixels,
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       int srcRB, const SkFilterPtrProc* proc_table)
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int ix = fx >> 16;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPMColor *p00, *p01, *p10, *p11;
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    p00 = p01 = srcPixels + SkClampMax(ix, srcMaxX);
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned)ix < srcMaxX)
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p01 += 1;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    p10 = (const SkPMColor*)((const char*)p00 + srcRB);
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    p11 = (const SkPMColor*)((const char*)p01 + srcRB);
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFilterPtrProc proc = SkGetBilinearFilterPtrXProc(proc_table, fx);
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return proc(p00, p01, p10, p11);
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid ARGB32_Clamp_Bilinear_BitmapShader::shadeSpan(int x, int y, SkPMColor dstC[], int count)
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count > 0);
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned srcScale = SkAlpha255To256(this->getPaintAlpha());
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkMatrix& inv = this->getTotalInverse();
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkBitmap& srcBitmap = this->getSrcBitmap();
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned        srcMaxX = srcBitmap.width() - 1;
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned        srcMaxY = srcBitmap.height() - 1;
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned        srcRB = srcBitmap.rowBytes();
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkFilterPtrProc* proc_table = SkGetBilinearFilterPtrProcTable();
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPMColor* srcPixels = (const SkPMColor*)srcBitmap.getPixels();
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->getInverseClass() == kPerspective_MatrixClass)
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                SkIntToScalar(y) + SK_ScalarHalf, count);
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (256 == srcScale)
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while ((count = iter.next()) != 0)
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkFixed* srcXY = iter.getXY();
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                while (--count >= 0)
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                {
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed fx = *srcXY++ - SK_FixedHalf;
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed fy = *srcXY++ - SK_FixedHalf;
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else    // scale by srcScale
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while ((count = iter.next()) != 0)
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkFixed* srcXY = iter.getXY();
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                while (--count >= 0)
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                {
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed fx = *srcXY++ - SK_FixedHalf;
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed fy = *srcXY++ - SK_FixedHalf;
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *dstC++ = SkAlphaMulQ(c, srcScale);
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else    // linear case
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkFixed fx, fy, dx, dy;
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now init fx, fy, dx, dy
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPoint srcPt;
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf,
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                             SkIntToScalar(y) + SK_ScalarHalf,
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                             &srcPt);
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf;
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf;
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dx = SkScalarToFixed(inv.getScaleX());
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dy = SkScalarToFixed(inv.getSkewY());
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (dy == 0 && (unsigned)(fy >> 16) < srcMaxY)
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            srcPixels = (const SkPMColor*)((const char*)srcPixels + (fy >> 16) * srcRB);
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            proc_table = SkGetBilinearFilterPtrProcYTable(proc_table, fy);
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (256 == srcScale)
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                do {
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *dstC++ = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fx += dx;
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } while (--count != 0);
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                do {
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkPMColor c = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *dstC++ = SkAlphaMulQ(c, srcScale);
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fx += dx;
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } while (--count != 0);
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else    // dy is != 0
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (256 == srcScale)
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                do {
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fx += dx;
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fy += dy;
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } while (--count != 0);
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                do {
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *dstC++ = SkAlphaMulQ(c, srcScale);
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fx += dx;
1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fy += dy;
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } while (--count != 0);
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
179