michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkFilterProc.h" michael@0: michael@0: class BILERP_BITMAP16_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader { michael@0: public: michael@0: BILERP_BITMAP16_SHADER_CLASS(const SkBitmap& src) michael@0: : HasSpan16_Sampler_BitmapShader(src, true, michael@0: SkShader::kClamp_TileMode, michael@0: SkShader::kClamp_TileMode) michael@0: { michael@0: } michael@0: michael@0: virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) michael@0: { michael@0: SkASSERT(count > 0); michael@0: michael@0: U8CPU alpha = this->getPaintAlpha(); michael@0: michael@0: const SkMatrix& inv = this->getTotalInverse(); michael@0: const SkBitmap& srcBitmap = this->getSrcBitmap(); michael@0: unsigned srcMaxX = srcBitmap.width() - 1; michael@0: unsigned srcMaxY = srcBitmap.height() - 1; michael@0: unsigned srcRB = srcBitmap.rowBytes(); michael@0: michael@0: BILERP_BITMAP16_SHADER_PREAMBLE(srcBitmap); michael@0: michael@0: const SkFilterProc* proc_table = SkGetBilinearFilterProcTable(); michael@0: const BILERP_BITMAP16_SHADER_TYPE* srcPixels = (const BILERP_BITMAP16_SHADER_TYPE*)srcBitmap.getPixels(); michael@0: michael@0: if (this->getInverseClass() == kPerspective_MatrixClass) michael@0: { michael@0: SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, count); michael@0: while ((count = iter.next()) != 0) michael@0: { michael@0: const SkFixed* srcXY = iter.getXY(); michael@0: while (--count >= 0) michael@0: { michael@0: SkFixed fx = *srcXY++ - SK_FixedHalf; michael@0: SkFixed fy = *srcXY++ - SK_FixedHalf; michael@0: int ix = fx >> 16; michael@0: int iy = fy >> 16; michael@0: int x = SkClampMax(ix, srcMaxX); michael@0: int y = SkClampMax(iy, srcMaxY); michael@0: michael@0: const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; michael@0: michael@0: p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + y * srcRB)) + x; michael@0: if ((unsigned)ix < srcMaxX) michael@0: p01 += 1; michael@0: p10 = p00; michael@0: p11 = p01; michael@0: if ((unsigned)iy < srcMaxY) michael@0: { michael@0: p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); michael@0: p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); michael@0: } michael@0: michael@0: SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); michael@0: uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); michael@0: michael@0: *dstC++ = expanded_rgb16_to_8888(c, alpha); michael@0: } michael@0: } michael@0: } michael@0: else // linear case michael@0: { michael@0: SkFixed fx, fy, dx, dy; michael@0: michael@0: // now init fx, fy, dx, dy michael@0: { michael@0: SkPoint srcPt; michael@0: this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, &srcPt); michael@0: michael@0: fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf; michael@0: fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf; michael@0: michael@0: if (this->getInverseClass() == kFixedStepInX_MatrixClass) michael@0: (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); michael@0: else michael@0: { michael@0: dx = SkScalarToFixed(inv.getScaleX()); michael@0: dy = SkScalarToFixed(inv.getSkewY()); michael@0: } michael@0: } michael@0: michael@0: do { michael@0: int ix = fx >> 16; michael@0: int iy = fy >> 16; michael@0: michael@0: const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; michael@0: michael@0: p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + michael@0: SkClampMax(iy, srcMaxY) * srcRB)) + michael@0: SkClampMax(ix, srcMaxX); michael@0: if ((unsigned)ix < srcMaxX) michael@0: p01 += 1; michael@0: p10 = p00; michael@0: p11 = p01; michael@0: if ((unsigned)iy < srcMaxY) michael@0: { michael@0: p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); michael@0: p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); michael@0: } michael@0: michael@0: SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); michael@0: uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); michael@0: *dstC++ = expanded_rgb16_to_8888(c, alpha); michael@0: michael@0: fx += dx; michael@0: fy += dy; michael@0: } while (--count != 0); michael@0: } michael@0: BILERP_BITMAP16_SHADER_POSTAMBLE(srcBitmap); michael@0: } michael@0: michael@0: virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) michael@0: { michael@0: SkASSERT(count > 0); michael@0: michael@0: const SkMatrix& inv = this->getTotalInverse(); michael@0: const SkBitmap& srcBitmap = this->getSrcBitmap(); michael@0: unsigned srcMaxX = srcBitmap.width() - 1; michael@0: unsigned srcMaxY = srcBitmap.height() - 1; michael@0: unsigned srcRB = srcBitmap.rowBytes(); michael@0: michael@0: BILERP_BITMAP16_SHADER_PREAMBLE(srcBitmap); michael@0: michael@0: const SkFilterProc* proc_table = SkGetBilinearFilterProcTable(); michael@0: const BILERP_BITMAP16_SHADER_TYPE* srcPixels = (const BILERP_BITMAP16_SHADER_TYPE*)srcBitmap.getPixels(); michael@0: michael@0: if (this->getInverseClass() == kPerspective_MatrixClass) michael@0: { michael@0: SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, count); michael@0: while ((count = iter.next()) != 0) michael@0: { michael@0: const SkFixed* srcXY = iter.getXY(); michael@0: while (--count >= 0) michael@0: { michael@0: SkFixed fx = *srcXY++ - SK_FixedHalf; michael@0: SkFixed fy = *srcXY++ - SK_FixedHalf; michael@0: int ix = fx >> 16; michael@0: int iy = fy >> 16; michael@0: michael@0: const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; michael@0: michael@0: p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + michael@0: SkClampMax(iy, srcMaxY) * srcRB)) + michael@0: SkClampMax(ix, srcMaxX); michael@0: if ((unsigned)ix < srcMaxX) michael@0: p01 += 1; michael@0: p10 = p00; michael@0: p11 = p01; michael@0: if ((unsigned)iy < srcMaxY) michael@0: { michael@0: p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); michael@0: p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); michael@0: } michael@0: michael@0: SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); michael@0: uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); michael@0: *dstC++ = SkCompact_rgb_16(c); michael@0: } michael@0: } michael@0: } michael@0: else // linear case michael@0: { michael@0: SkFixed fx, fy, dx, dy; michael@0: michael@0: // now init fx, fy, dx, dy michael@0: { michael@0: SkPoint srcPt; michael@0: this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, &srcPt); michael@0: michael@0: fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf; michael@0: fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf; michael@0: michael@0: if (this->getInverseClass() == kFixedStepInX_MatrixClass) michael@0: (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); michael@0: else michael@0: { michael@0: dx = SkScalarToFixed(inv.getScaleX()); michael@0: dy = SkScalarToFixed(inv.getSkewY()); michael@0: } michael@0: } michael@0: michael@0: do { michael@0: int ix = fx >> 16; michael@0: int iy = fy >> 16; michael@0: michael@0: const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; michael@0: michael@0: p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + michael@0: SkClampMax(iy, srcMaxY) * srcRB)) + michael@0: SkClampMax(ix, srcMaxX); michael@0: if ((unsigned)ix < srcMaxX) michael@0: p01 += 1; michael@0: p10 = p00; michael@0: p11 = p01; michael@0: if ((unsigned)iy < srcMaxY) michael@0: { michael@0: p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); michael@0: p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); michael@0: } michael@0: michael@0: SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); michael@0: uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), michael@0: SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); michael@0: *dstC++ = SkCompact_rgb_16(c); michael@0: michael@0: fx += dx; michael@0: fy += dy; michael@0: } while (--count != 0); michael@0: } michael@0: BILERP_BITMAP16_SHADER_POSTAMBLE(srcBitmap); michael@0: } michael@0: }; michael@0: michael@0: #undef BILERP_BITMAP16_SHADER_CLASS michael@0: #undef BILERP_BITMAP16_SHADER_TYPE michael@0: #undef BILERP_BITMAP16_SHADER_PREAMBLE michael@0: #undef BILERP_BITMAP16_SHADER_PIXEL michael@0: #undef BILERP_BITMAP16_SHADER_POSTAMBLE