
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */



#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE
    #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb)
#endif
#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE
    #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap)
#endif
#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE16
    #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb)
#endif
#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE16
    #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap)
#endif

class NOFILTER_BITMAP_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader {
public:
    NOFILTER_BITMAP_SHADER_CLASS(const SkBitmap& src)
        : HasSpan16_Sampler_BitmapShader(src, false,
                                         NOFILTER_BITMAP_SHADER_TILEMODE,
                                         NOFILTER_BITMAP_SHADER_TILEMODE)
    {
    }

    virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
    {
        if (!this->INHERITED::setContext(device, paint, matrix))
            return false;

#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
        this->computeUnitInverse();
#endif
        return true;
    }

    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
    {
        SkASSERT(count > 0);

#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC32
        if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
        {
            NOFILTER_BITMAP_SHADER_SPRITEPROC32(this, x, y, dstC, count);
            return;
        }
#endif

        unsigned        scale = SkAlpha255To256(this->getPaintAlpha());
#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
        const SkMatrix& inv = this->getUnitInverse();
        SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
#else
        const SkMatrix& inv = this->getTotalInverse();
        SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
#endif
        const SkBitmap& srcBitmap = this->getSrcBitmap();
        unsigned        srcMaxX = srcBitmap.width() - 1;
        unsigned        srcMaxY = srcBitmap.height() - 1;
        unsigned        srcRB = srcBitmap.rowBytes();
        SkFixed         fx, fy, dx, dy;

        const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
        NOFILTER_BITMAP_SHADER_PREAMBLE(srcBitmap, srcRB);

        if (this->getInverseClass() == kPerspective_MatrixClass)
        {
            SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
                                    SkIntToScalar(y) + SK_ScalarHalf, count);
            while ((count = iter.next()) != 0)
            {
                const SkFixed* srcXY = iter.getXY();

/*  Do I need this?
#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
            fx >>= level;
            fy >>= level;
#endif
*/
                if (256 == scale)
                {
                    while (--count >= 0)
                    {
                        fx = *srcXY++;
                        fy = *srcXY++;
                        unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                        unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
                        *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
                    }
                }
                else
                {
                    while (--count >= 0)
                    {
                        fx = *srcXY++;
                        fy = *srcXY++;
                        unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                        unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
                        uint32_t c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
                        *dstC++ = SkAlphaMulQ(c, scale);
                    }
                }
            }
            return;
        }

        // now init fx, fy, dx, dy
        {
            SkPoint srcPt;
            invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
                         SkIntToScalar(y) + SK_ScalarHalf, &srcPt);

            fx = SkScalarToFixed(srcPt.fX);
            fy = SkScalarToFixed(srcPt.fY);

            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
            else
            {
                dx = SkScalarToFixed(inv.getScaleX());
                dy = SkScalarToFixed(inv.getSkewY());
            }
        }

#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
        {   int level = this->getMipLevel() >> 16;
            fx >>= level;
            fy >>= level;
            dx >>= level;
            dy >>= level;
        }
#endif

        if (dy == 0)
        {
            int y_index = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
//          SkDEBUGF(("fy = %g, srcMaxY = %d, y_index = %d\n", SkFixedToFloat(fy), srcMaxY, y_index));
            srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + y_index * srcRB);
            if (scale == 256)
                while (--count >= 0)
                {
                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                    fx += dx;
                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
                }
            else
                while (--count >= 0)
                {
                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                    SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
                    fx += dx;
                    *dstC++ = SkAlphaMulQ(c, scale);
                }
        }
        else    // dy != 0
        {
            if (scale == 256)
                while (--count >= 0)
                {
                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
                    fx += dx;
                    fy += dy;
                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
                }
            else
                while (--count >= 0)
                {
                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
                    SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
                    fx += dx;
                    fy += dy;
                    *dstC++ = SkAlphaMulQ(c, scale);
                }
        }

        NOFILTER_BITMAP_SHADER_POSTAMBLE(srcBitmap);
    }

    virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count)
    {
        SkASSERT(count > 0);
        SkASSERT(this->getFlags() & SkShader::kHasSpan16_Flag);

#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC16
        if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
        {
            NOFILTER_BITMAP_SHADER_SPRITEPROC16(this, x, y, dstC, count);
            return;
        }
#endif

#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
        const SkMatrix& inv = this->getUnitInverse();
        SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
#else
        const SkMatrix& inv = this->getTotalInverse();
        SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
#endif
        const SkBitmap& srcBitmap = this->getSrcBitmap();
        unsigned        srcMaxX = srcBitmap.width() - 1;
        unsigned        srcMaxY = srcBitmap.height() - 1;
        unsigned        srcRB = srcBitmap.rowBytes();
        SkFixed         fx, fy, dx, dy;

        const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
        NOFILTER_BITMAP_SHADER_PREAMBLE16(srcBitmap, srcRB);

        if (this->getInverseClass() == kPerspective_MatrixClass)
        {
            SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
                                    SkIntToScalar(y) + SK_ScalarHalf, count);
            while ((count = iter.next()) != 0)
            {
                const SkFixed* srcXY = iter.getXY();

                while (--count >= 0)
                {
                    fx = *srcXY++;
                    fy = *srcXY++;
                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
                }
            }
            return;
        }

        // now init fx, fy, dx, dy
        {
            SkPoint srcPt;
            invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
                         SkIntToScalar(y) + SK_ScalarHalf, &srcPt);

            fx = SkScalarToFixed(srcPt.fX);
            fy = SkScalarToFixed(srcPt.fY);

            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
            else
            {
                dx = SkScalarToFixed(inv.getScaleX());
                dy = SkScalarToFixed(inv.getSkewY());
            }
        }

#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
        {   int level = this->getMipLevel() >> 16;
            fx >>= level;
            fy >>= level;
            dx >>= level;
            dy >>= level;
        }
#endif

        if (dy == 0)
        {
            srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY) * srcRB);
            do {
                unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                fx += dx;
                *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X16(srcPixels, x);
            } while (--count != 0);
        }
        else    // dy != 0
        {
            do {
                unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
                unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
                fx += dx;
                fy += dy;
                *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
            } while (--count != 0);
        }

        NOFILTER_BITMAP_SHADER_POSTAMBLE16(srcBitmap);
    }
private:
    typedef HasSpan16_Sampler_BitmapShader INHERITED;
};

#undef NOFILTER_BITMAP_SHADER_CLASS
#undef NOFILTER_BITMAP_SHADER_TYPE
#undef NOFILTER_BITMAP_SHADER_PREAMBLE
#undef NOFILTER_BITMAP_SHADER_POSTAMBLE
#undef NOFILTER_BITMAP_SHADER_SAMPLE_X      //(x)
#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY     //(x, y, rowBytes)
#undef NOFILTER_BITMAP_SHADER_TILEMODE
#undef NOFILTER_BITMAP_SHADER_TILEPROC

#undef NOFILTER_BITMAP_SHADER_PREAMBLE16
#undef NOFILTER_BITMAP_SHADER_POSTAMBLE16
#undef NOFILTER_BITMAP_SHADER_SAMPLE_X16        //(x)
#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY16       //(x, y, rowBytes)

#undef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
#undef NOFILTER_BITMAP_SHADER_SPRITEPROC16
#undef NOFILTER_BITMAP_SHADER_SPRITEPROC32
