| |
| /* |
| * 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. |
| */ |
| |
| |
| #include "SkFilterProc.h" |
| |
| class BILERP_BITMAP16_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader { |
| public: |
| BILERP_BITMAP16_SHADER_CLASS(const SkBitmap& src) |
| : HasSpan16_Sampler_BitmapShader(src, true, |
| SkShader::kClamp_TileMode, |
| SkShader::kClamp_TileMode) |
| { |
| } |
| |
| virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) |
| { |
| SkASSERT(count > 0); |
| |
| U8CPU alpha = this->getPaintAlpha(); |
| |
| const SkMatrix& inv = this->getTotalInverse(); |
| const SkBitmap& srcBitmap = this->getSrcBitmap(); |
| unsigned srcMaxX = srcBitmap.width() - 1; |
| unsigned srcMaxY = srcBitmap.height() - 1; |
| unsigned srcRB = srcBitmap.rowBytes(); |
| |
| BILERP_BITMAP16_SHADER_PREAMBLE(srcBitmap); |
| |
| const SkFilterProc* proc_table = SkGetBilinearFilterProcTable(); |
| const BILERP_BITMAP16_SHADER_TYPE* srcPixels = (const BILERP_BITMAP16_SHADER_TYPE*)srcBitmap.getPixels(); |
| |
| 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) |
| { |
| SkFixed fx = *srcXY++ - SK_FixedHalf; |
| SkFixed fy = *srcXY++ - SK_FixedHalf; |
| int ix = fx >> 16; |
| int iy = fy >> 16; |
| int x = SkClampMax(ix, srcMaxX); |
| int y = SkClampMax(iy, srcMaxY); |
| |
| const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; |
| |
| p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + y * srcRB)) + x; |
| if ((unsigned)ix < srcMaxX) |
| p01 += 1; |
| p10 = p00; |
| p11 = p01; |
| if ((unsigned)iy < srcMaxY) |
| { |
| p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); |
| p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); |
| } |
| |
| SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); |
| uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); |
| |
| *dstC++ = expanded_rgb16_to_8888(c, alpha); |
| } |
| } |
| } |
| else // linear case |
| { |
| SkFixed fx, fy, dx, dy; |
| |
| // now init fx, fy, dx, dy |
| { |
| SkPoint srcPt; |
| this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf, |
| SkIntToScalar(y) + SK_ScalarHalf, &srcPt); |
| |
| fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf; |
| fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf; |
| |
| if (this->getInverseClass() == kFixedStepInX_MatrixClass) |
| (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); |
| else |
| { |
| dx = SkScalarToFixed(inv.getScaleX()); |
| dy = SkScalarToFixed(inv.getSkewY()); |
| } |
| } |
| |
| do { |
| int ix = fx >> 16; |
| int iy = fy >> 16; |
| |
| const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; |
| |
| p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + |
| SkClampMax(iy, srcMaxY) * srcRB)) + |
| SkClampMax(ix, srcMaxX); |
| if ((unsigned)ix < srcMaxX) |
| p01 += 1; |
| p10 = p00; |
| p11 = p01; |
| if ((unsigned)iy < srcMaxY) |
| { |
| p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); |
| p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); |
| } |
| |
| SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); |
| uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); |
| *dstC++ = expanded_rgb16_to_8888(c, alpha); |
| |
| fx += dx; |
| fy += dy; |
| } while (--count != 0); |
| } |
| BILERP_BITMAP16_SHADER_POSTAMBLE(srcBitmap); |
| } |
| |
| virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) |
| { |
| SkASSERT(count > 0); |
| |
| const SkMatrix& inv = this->getTotalInverse(); |
| const SkBitmap& srcBitmap = this->getSrcBitmap(); |
| unsigned srcMaxX = srcBitmap.width() - 1; |
| unsigned srcMaxY = srcBitmap.height() - 1; |
| unsigned srcRB = srcBitmap.rowBytes(); |
| |
| BILERP_BITMAP16_SHADER_PREAMBLE(srcBitmap); |
| |
| const SkFilterProc* proc_table = SkGetBilinearFilterProcTable(); |
| const BILERP_BITMAP16_SHADER_TYPE* srcPixels = (const BILERP_BITMAP16_SHADER_TYPE*)srcBitmap.getPixels(); |
| |
| 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) |
| { |
| SkFixed fx = *srcXY++ - SK_FixedHalf; |
| SkFixed fy = *srcXY++ - SK_FixedHalf; |
| int ix = fx >> 16; |
| int iy = fy >> 16; |
| |
| const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; |
| |
| p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + |
| SkClampMax(iy, srcMaxY) * srcRB)) + |
| SkClampMax(ix, srcMaxX); |
| if ((unsigned)ix < srcMaxX) |
| p01 += 1; |
| p10 = p00; |
| p11 = p01; |
| if ((unsigned)iy < srcMaxY) |
| { |
| p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); |
| p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); |
| } |
| |
| SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); |
| uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); |
| *dstC++ = SkCompact_rgb_16(c); |
| } |
| } |
| } |
| else // linear case |
| { |
| SkFixed fx, fy, dx, dy; |
| |
| // now init fx, fy, dx, dy |
| { |
| SkPoint srcPt; |
| this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf, |
| SkIntToScalar(y) + SK_ScalarHalf, &srcPt); |
| |
| fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf; |
| fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf; |
| |
| if (this->getInverseClass() == kFixedStepInX_MatrixClass) |
| (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); |
| else |
| { |
| dx = SkScalarToFixed(inv.getScaleX()); |
| dy = SkScalarToFixed(inv.getSkewY()); |
| } |
| } |
| |
| do { |
| int ix = fx >> 16; |
| int iy = fy >> 16; |
| |
| const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11; |
| |
| p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + |
| SkClampMax(iy, srcMaxY) * srcRB)) + |
| SkClampMax(ix, srcMaxX); |
| if ((unsigned)ix < srcMaxX) |
| p01 += 1; |
| p10 = p00; |
| p11 = p01; |
| if ((unsigned)iy < srcMaxY) |
| { |
| p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB); |
| p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB); |
| } |
| |
| SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy); |
| uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)), |
| SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11))); |
| *dstC++ = SkCompact_rgb_16(c); |
| |
| fx += dx; |
| fy += dy; |
| } while (--count != 0); |
| } |
| BILERP_BITMAP16_SHADER_POSTAMBLE(srcBitmap); |
| } |
| }; |
| |
| #undef BILERP_BITMAP16_SHADER_CLASS |
| #undef BILERP_BITMAP16_SHADER_TYPE |
| #undef BILERP_BITMAP16_SHADER_PREAMBLE |
| #undef BILERP_BITMAP16_SHADER_PIXEL |
| #undef BILERP_BITMAP16_SHADER_POSTAMBLE |