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