SkGradientShader.cpp revision d7cc651b8da11d52ae90e910b948f5e2d15daaf9
1589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 3589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Copyright 2006 The Android Open Source Project 4589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * 5589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Use of this source code is governed by a BSD-style license that can be 6589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * found in the LICENSE file. 7589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 8589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 9589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkGradientShaderPriv.h" 10589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkLinearGradient.h" 11589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkRadialGradient.h" 12589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkTwoPointRadialGradient.h" 13589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkTwoPointConicalGradient.h" 14589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkSweepGradient.h" 15589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 16589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkGradientShaderBase::SkGradientShaderBase(const SkColor colors[], const SkScalar pos[], 17589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper) { 18589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(colorCount > 1); 19589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 20589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return 21589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 22589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fMapper = mapper; 23589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkSafeRef(mapper); 24589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 25589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT((unsigned)mode < SkShader::kTileModeCount); 26589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); 27589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fTileMode = mode; 28589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fTileProc = gTileProcs[mode]; 29589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 30589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16 = fCache16Storage = NULL; 31589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32 = NULL; 32589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32PixelRef = NULL; 33589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 34589708bf7c706348b763e8277004cb160b202bdbrileya@google.com /* Note: we let the caller skip the first and/or last position. 35589708bf7c706348b763e8277004cb160b202bdbrileya@google.com i.e. pos[0] = 0.3, pos[1] = 0.7 36589708bf7c706348b763e8277004cb160b202bdbrileya@google.com In these cases, we insert dummy entries to ensure that the final data 37589708bf7c706348b763e8277004cb160b202bdbrileya@google.com will be bracketed by [0, 1]. 38589708bf7c706348b763e8277004cb160b202bdbrileya@google.com i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 39589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 40589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Thus colorCount (the caller's value, and fColorCount (our value) may 41589708bf7c706348b763e8277004cb160b202bdbrileya@google.com differ by up to 2. In the above example: 42589708bf7c706348b763e8277004cb160b202bdbrileya@google.com colorCount = 2 43589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fColorCount = 4 44589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 45589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fColorCount = colorCount; 46589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // check if we need to add in dummy start and/or end position/colors 47589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bool dummyFirst = false; 48589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bool dummyLast = false; 49589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (pos) { 50589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dummyFirst = pos[0] != 0; 51589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dummyLast = pos[colorCount - 1] != SK_Scalar1; 52589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fColorCount += dummyFirst + dummyLast; 53589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 54589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 55589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount > kColorStorageCount) { 56589708bf7c706348b763e8277004cb160b202bdbrileya@google.com size_t size = sizeof(SkColor) + sizeof(Rec); 57589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOrigColors = reinterpret_cast<SkColor*>( 58589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_malloc_throw(size * fColorCount)); 59589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 60589708bf7c706348b763e8277004cb160b202bdbrileya@google.com else { 61589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOrigColors = fStorage; 62589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 63589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 64589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Now copy over the colors, adding the dummies as needed 65589708bf7c706348b763e8277004cb160b202bdbrileya@google.com { 66589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkColor* origColors = fOrigColors; 67589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (dummyFirst) { 68589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *origColors++ = colors[0]; 69589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 70589708bf7c706348b763e8277004cb160b202bdbrileya@google.com memcpy(origColors, colors, colorCount * sizeof(SkColor)); 71589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (dummyLast) { 72589708bf7c706348b763e8277004cb160b202bdbrileya@google.com origColors += colorCount; 73589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *origColors = colors[colorCount - 1]; 74589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 75589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 76589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 77589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fRecs = (Rec*)(fOrigColors + fColorCount); 78589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount > 2) { 79589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Rec* recs = fRecs; 80589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs->fPos = 0; 81589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // recs->fScale = 0; // unused; 82589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs += 1; 83589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (pos) { 84589708bf7c706348b763e8277004cb160b202bdbrileya@google.com /* We need to convert the user's array of relative positions into 85589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fixed-point positions and scale factors. We need these results 86589708bf7c706348b763e8277004cb160b202bdbrileya@google.com to be strictly monotonic (no two values equal or out of order). 87589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Hence this complex loop that just jams a zero for the scale 88589708bf7c706348b763e8277004cb160b202bdbrileya@google.com value if it sees a segment out of order, and it assures that 89589708bf7c706348b763e8277004cb160b202bdbrileya@google.com we start at 0 and end at 1.0 90589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 91589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed prev = 0; 92589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int startIndex = dummyFirst ? 0 : 1; 93589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count = colorCount + dummyLast; 94589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = startIndex; i < count; i++) { 95589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // force the last value to be 1.0 96589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed curr; 97589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (i == colorCount) { // we're really at the dummyLast 98589708bf7c706348b763e8277004cb160b202bdbrileya@google.com curr = SK_Fixed1; 99589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 100589708bf7c706348b763e8277004cb160b202bdbrileya@google.com curr = SkScalarToFixed(pos[i]); 101589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 102589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // pin curr withing range 103589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (curr < 0) { 104589708bf7c706348b763e8277004cb160b202bdbrileya@google.com curr = 0; 105589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else if (curr > SK_Fixed1) { 106589708bf7c706348b763e8277004cb160b202bdbrileya@google.com curr = SK_Fixed1; 107589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 108589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs->fPos = curr; 109589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (curr > prev) { 110589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs->fScale = (1 << 24) / (curr - prev); 111589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 112589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs->fScale = 0; // ignore this segment 113589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 114589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // get ready for the next value 115589708bf7c706348b763e8277004cb160b202bdbrileya@google.com prev = curr; 116589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs += 1; 117589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 118589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { // assume even distribution 119589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dp = SK_Fixed1 / (colorCount - 1); 120589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed p = dp; 121589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed scale = (colorCount - 1) << 8; // (1 << 24) / dp 122589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 1; i < colorCount; i++) { 123589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs->fPos = p; 124589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs->fScale = scale; 125589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs += 1; 126589708bf7c706348b763e8277004cb160b202bdbrileya@google.com p += dp; 127589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 128589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 129589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 130589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->initCommon(); 131589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 132589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 133589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : 134589708bf7c706348b763e8277004cb160b202bdbrileya@google.com INHERITED(buffer) { 135589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCacheAlpha = 256; 136589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 137589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fMapper = static_cast<SkUnitMapper*>(buffer.readFlattenable()); 138589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 139589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16 = fCache16Storage = NULL; 140589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32 = NULL; 141589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32PixelRef = NULL; 142589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 143589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int colorCount = fColorCount = buffer.readU32(); 144589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (colorCount > kColorStorageCount) { 145589708bf7c706348b763e8277004cb160b202bdbrileya@google.com size_t size = sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec); 146589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOrigColors = (SkColor*)sk_malloc_throw(size * colorCount); 147589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 148589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOrigColors = fStorage; 149589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 150589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.read(fOrigColors, colorCount * sizeof(SkColor)); 151589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 152589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fTileMode = (TileMode)buffer.readU8(); 153589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fTileProc = gTileProcs[fTileMode]; 154589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fRecs = (Rec*)(fOrigColors + colorCount); 155589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (colorCount > 2) { 156589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Rec* recs = fRecs; 157589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs[0].fPos = 0; 158589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 1; i < colorCount; i++) { 159589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs[i].fPos = buffer.readS32(); 160589708bf7c706348b763e8277004cb160b202bdbrileya@google.com recs[i].fScale = buffer.readU32(); 161589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 162589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 163589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.readMatrix(&fPtsToUnit); 164589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->initCommon(); 165589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 166589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 167589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkGradientShaderBase::~SkGradientShaderBase() { 168589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fCache16Storage) { 169589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_free(fCache16Storage); 170589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 171589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkSafeUnref(fCache32PixelRef); 172589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fOrigColors != fStorage) { 173589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_free(fOrigColors); 174589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 175589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkSafeUnref(fMapper); 176589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 177589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 178589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::initCommon() { 179589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fFlags = 0; 180589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned colorAlpha = 0xFF; 181589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < fColorCount; i++) { 182589708bf7c706348b763e8277004cb160b202bdbrileya@google.com colorAlpha &= SkColorGetA(fOrigColors[i]); 183589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 184589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fColorsAreOpaque = colorAlpha == 0xFF; 185589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 186589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 187589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const { 188589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->INHERITED::flatten(buffer); 189589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeFlattenable(fMapper); 190589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.write32(fColorCount); 191589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeMul4(fOrigColors, fColorCount * sizeof(SkColor)); 192589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.write8(fTileMode); 193589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount > 2) { 194589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Rec* recs = fRecs; 195589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 1; i < fColorCount; i++) { 196589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.write32(recs[i].fPos); 197589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.write32(recs[i].fScale); 198589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 199589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 200589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeMatrix(fPtsToUnit); 201589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 202589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 203589708bf7c706348b763e8277004cb160b202bdbrileya@google.combool SkGradientShaderBase::isOpaque() const { 204589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return fColorsAreOpaque; 205589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 206589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 207589708bf7c706348b763e8277004cb160b202bdbrileya@google.combool SkGradientShaderBase::setContext(const SkBitmap& device, 208589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPaint& paint, 209589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkMatrix& matrix) { 210589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (!this->INHERITED::setContext(device, paint, matrix)) { 211589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 212589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 213589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 214589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkMatrix& inverse = this->getTotalInverse(); 215589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 216589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) { 217589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 218589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 219589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 220589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDstToIndexProc = fDstToIndex.getMapXYProc(); 221589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex); 222589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 223589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // now convert our colors in to PMColors 224589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned paintAlpha = this->getPaintAlpha(); 225589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 226589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fFlags = this->INHERITED::getFlags(); 227589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorsAreOpaque && paintAlpha == 0xFF) { 228589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fFlags |= kOpaqueAlpha_Flag; 229589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 230589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // we can do span16 as long as our individual colors are opaque, 231589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // regardless of the paint's alpha 232589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorsAreOpaque) { 233589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fFlags |= kHasSpan16_Flag; 234589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 235589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 236589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->setCacheAlpha(paintAlpha); 237589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return true; 238589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 239589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 240589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { 241589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // if the new alpha differs from the previous time we were called, inval our cache 242589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // this will trigger the cache to be rebuilt. 243589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // we don't care about the first time, since the cache ptrs will already be NULL 244589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fCacheAlpha != alpha) { 245589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16 = NULL; // inval the cache 246589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32 = NULL; // inval the cache 247589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCacheAlpha = alpha; // record the new alpha 248589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // inform our subclasses 249589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fCache32PixelRef) { 250589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32PixelRef->notifyPixelsChanged(); 251589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 252589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 253589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 254589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 255589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) 256589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 257589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/** We take the original colors, not our premultiplied PMColors, since we can 258589708bf7c706348b763e8277004cb160b202bdbrileya@google.com build a 16bit table as long as the original colors are opaque, even if the 259589708bf7c706348b763e8277004cb160b202bdbrileya@google.com paint specifies a non-opaque alpha. 260589708bf7c706348b763e8277004cb160b202bdbrileya@google.com*/ 261589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1, 262589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count) { 263589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 1); 264589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(SkColorGetA(c0) == 0xFF); 265589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(SkColorGetA(c1) == 0xFF); 266589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 267589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed r = SkColorGetR(c0); 268589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed g = SkColorGetG(c0); 269589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed b = SkColorGetB(c0); 270589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 271589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); 272589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); 273589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1); 274589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 275589708bf7c706348b763e8277004cb160b202bdbrileya@google.com r = SkIntToFixed(r) + 0x8000; 276589708bf7c706348b763e8277004cb160b202bdbrileya@google.com g = SkIntToFixed(g) + 0x8000; 277589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b = SkIntToFixed(b) + 0x8000; 278589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 279589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 280589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned rr = r >> 16; 281589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned gg = g >> 16; 282589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned bb = b >> 16; 283589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb)); 284589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb); 285589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache += 1; 286589708bf7c706348b763e8277004cb160b202bdbrileya@google.com r += dr; 287589708bf7c706348b763e8277004cb160b202bdbrileya@google.com g += dg; 288589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b += db; 289589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 290589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 291589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 292589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 293589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * 2x2 dither a fixed-point color component (8.16) down to 8, matching the 294589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * semantics of how we 2x2 dither 32->16 295589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 296589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline U8CPU dither_fixed_to_8(SkFixed n) { 297589708bf7c706348b763e8277004cb160b202bdbrileya@google.com n >>= 8; 298589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return ((n << 1) - ((n >> 8 << 8) | (n >> 8))) >> 8; 299589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 300589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 301589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 302589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * For dithering with premultiply, we want to ceiling the alpha component, 303589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * to ensure that it is always >= any color component. 304589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 305589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline U8CPU dither_ceil_fixed_to_8(SkFixed n) { 306589708bf7c706348b763e8277004cb160b202bdbrileya@google.com n >>= 8; 307589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return ((n << 1) - (n | (n >> 8))) >> 8; 308589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 309589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 310589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1, 311589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count, U8CPU paintAlpha) { 312589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 1); 313589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 314589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // need to apply paintAlpha to our two endpoints 315589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); 316589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed da; 317589708bf7c706348b763e8277004cb160b202bdbrileya@google.com { 318589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int tmp = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); 319589708bf7c706348b763e8277004cb160b202bdbrileya@google.com da = SkIntToFixed(tmp - a) / (count - 1); 320589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 321589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 322589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed r = SkColorGetR(c0); 323589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed g = SkColorGetG(c0); 324589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed b = SkColorGetB(c0); 325589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); 326589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); 327589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1); 328589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 329589708bf7c706348b763e8277004cb160b202bdbrileya@google.com a = SkIntToFixed(a) + 0x8000; 330589708bf7c706348b763e8277004cb160b202bdbrileya@google.com r = SkIntToFixed(r) + 0x8000; 331589708bf7c706348b763e8277004cb160b202bdbrileya@google.com g = SkIntToFixed(g) + 0x8000; 332589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b = SkIntToFixed(b) + 0x8000; 333589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 334589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 335589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[0] = SkPremultiplyARGBInline(a >> 16, r >> 16, g >> 16, b >> 16); 336589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[kCache32Count] = 337589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPremultiplyARGBInline(dither_ceil_fixed_to_8(a), 338589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dither_fixed_to_8(r), 339589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dither_fixed_to_8(g), 340589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dither_fixed_to_8(b)); 341589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache += 1; 342589708bf7c706348b763e8277004cb160b202bdbrileya@google.com a += da; 343589708bf7c706348b763e8277004cb160b202bdbrileya@google.com r += dr; 344589708bf7c706348b763e8277004cb160b202bdbrileya@google.com g += dg; 345589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b += db; 346589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 347589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 348589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 349589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline int SkFixedToFFFF(SkFixed x) { 350589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT((unsigned)x <= SK_Fixed1); 351589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return x - (x >> 16); 352589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 353589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 354589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline U16CPU bitsTo16(unsigned x, const unsigned bits) { 355589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(x < (1U << bits)); 356589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (6 == bits) { 357589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return (x << 10) | (x << 4) | (x >> 2); 358589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 359589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (8 == bits) { 360589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return (x << 8) | x; 361589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 362589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_throw(); 363589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return 0; 364589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 365589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 366589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/** We duplicate the last value in each half of the cache so that 367589708bf7c706348b763e8277004cb160b202bdbrileya@google.com interpolation doesn't have to special-case being at the last point. 368589708bf7c706348b763e8277004cb160b202bdbrileya@google.com*/ 369589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic void complete_16bit_cache(uint16_t* cache, int stride) { 370589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[stride - 1] = cache[stride - 2]; 371589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[2 * stride - 1] = cache[2 * stride - 2]; 372589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 373589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 374589708bf7c706348b763e8277004cb160b202bdbrileya@google.comconst uint16_t* SkGradientShaderBase::getCache16() const { 375589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fCache16 == NULL) { 376589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // double the count for dither entries 377589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const int entryCount = kCache16Count * 2; 378589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const size_t allocSize = sizeof(uint16_t) * entryCount; 379589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 380589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fCache16Storage == NULL) { // set the storage and our working ptr 381589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); 382589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 383589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16 = fCache16Storage; 384589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount == 2) { 385589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], 386589708bf7c706348b763e8277004cb160b202bdbrileya@google.com kGradient16Length); 387589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 388589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Rec* rec = fRecs; 389589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int prevIndex = 0; 390589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 1; i < fColorCount; i++) { 391589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; 392589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(nextIndex < kCache16Count); 393589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 394589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (nextIndex > prevIndex) 395589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1); 396589708bf7c706348b763e8277004cb160b202bdbrileya@google.com prevIndex = nextIndex; 397589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 398589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // one extra space left over at the end for complete_16bit_cache() 399589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(prevIndex == kGradient16Length - 1); 400589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 401589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 402589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fMapper) { 403589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); 404589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* linear = fCache16; // just computed linear data 405589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* mapped = fCache16Storage; // storage for mapped data 406589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkUnitMapper* map = fMapper; 407589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < kGradient16Length; i++) { 408589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift; 409589708bf7c706348b763e8277004cb160b202bdbrileya@google.com mapped[i] = linear[index]; 410589708bf7c706348b763e8277004cb160b202bdbrileya@google.com mapped[i + kCache16Count] = linear[index + kCache16Count]; 411589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 412589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_free(fCache16); 413589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache16 = fCache16Storage; 414589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 415589708bf7c706348b763e8277004cb160b202bdbrileya@google.com complete_16bit_cache(fCache16, kCache16Count); 416589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 417589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return fCache16; 418589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 419589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 420589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/** We duplicate the last value in each half of the cache so that 421589708bf7c706348b763e8277004cb160b202bdbrileya@google.com interpolation doesn't have to special-case being at the last point. 422589708bf7c706348b763e8277004cb160b202bdbrileya@google.com*/ 423589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic void complete_32bit_cache(SkPMColor* cache, int stride) { 424589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[stride - 1] = cache[stride - 2]; 425589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[2 * stride - 1] = cache[2 * stride - 2]; 426589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 427589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 428589708bf7c706348b763e8277004cb160b202bdbrileya@google.comconst SkPMColor* SkGradientShaderBase::getCache32() const { 429589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fCache32 == NULL) { 430589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // double the count for dither entries 431589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const int entryCount = kCache32Count * 2; 432589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const size_t allocSize = sizeof(SkPMColor) * entryCount; 433589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 434589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (NULL == fCache32PixelRef) { 435589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef, 436589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (NULL, allocSize, NULL)); 437589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 438589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); 439589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount == 2) { 440589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], 441589708bf7c706348b763e8277004cb160b202bdbrileya@google.com kGradient32Length, fCacheAlpha); 442589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 443589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Rec* rec = fRecs; 444589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int prevIndex = 0; 445589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 1; i < fColorCount; i++) { 446589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; 447589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(nextIndex < kGradient32Length); 448589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 449589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (nextIndex > prevIndex) 450589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], 451589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOrigColors[i], 452589708bf7c706348b763e8277004cb160b202bdbrileya@google.com nextIndex - prevIndex + 1, fCacheAlpha); 453589708bf7c706348b763e8277004cb160b202bdbrileya@google.com prevIndex = nextIndex; 454589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 455589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(prevIndex == kGradient32Length - 1); 456589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 457589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 458589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fMapper) { 459589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef, 460589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (NULL, allocSize, NULL)); 461589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* linear = fCache32; // just computed linear data 462589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data 463589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkUnitMapper* map = fMapper; 464589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < kGradient32Length; i++) { 465589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int index = map->mapUnit16((i << 8) | i) >> 8; 466589708bf7c706348b763e8277004cb160b202bdbrileya@google.com mapped[i] = linear[index]; 467589708bf7c706348b763e8277004cb160b202bdbrileya@google.com mapped[i + kCache32Count] = linear[index + kCache32Count]; 468589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 469589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32PixelRef->unref(); 470589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32PixelRef = newPR; 471589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCache32 = (SkPMColor*)newPR->getAddr(); 472589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 473589708bf7c706348b763e8277004cb160b202bdbrileya@google.com complete_32bit_cache(fCache32, kCache32Count); 474589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 475589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return fCache32; 476589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 477589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 478589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 479589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Because our caller might rebuild the same (logically the same) gradient 480589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * over and over, we'd like to return exactly the same "bitmap" if possible, 481589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * allowing the client to utilize a cache of our bitmap (e.g. with a GPU). 482589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * To do that, we maintain a private cache of built-bitmaps, based on our 483589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * colors and positions. Note: we don't try to flatten the fMapper, so if one 484589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * is present, we skip the cache for now. 485589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 486589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::commonAsABitmap(SkBitmap* bitmap) const { 487589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // our caller assumes no external alpha, so we ensure that our cache is 488589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // built with 0xFF 489589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->setCacheAlpha(0xFF); 490589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 491589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // don't have a way to put the mapper into our cache-key yet 492589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fMapper) { 493589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // force our cahce32pixelref to be built 494589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)this->getCache32(); 495589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bitmap->setConfig(SkBitmap::kARGB_8888_Config, kGradient32Length, 1); 496589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bitmap->setPixelRef(fCache32PixelRef); 497589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return; 498589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 499589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 500589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // build our key: [numColors + colors[] + {positions[]} ] 501589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count = 1 + fColorCount; 502589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount > 2) { 503589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count += fColorCount - 1; // fRecs[].fPos 504589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 505589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 506589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkAutoSTMalloc<16, int32_t> storage(count); 507589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int32_t* buffer = storage.get(); 508589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 509589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *buffer++ = fColorCount; 510589708bf7c706348b763e8277004cb160b202bdbrileya@google.com memcpy(buffer, fOrigColors, fColorCount * sizeof(SkColor)); 511589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer += fColorCount; 512589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount > 2) { 513589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 1; i < fColorCount; i++) { 514589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *buffer++ = fRecs[i].fPos; 515589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 516589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 517589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(buffer - storage.get() == count); 518589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 519589708bf7c706348b763e8277004cb160b202bdbrileya@google.com /////////////////////////////////// 520589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 521589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SK_DECLARE_STATIC_MUTEX(gMutex); 522589708bf7c706348b763e8277004cb160b202bdbrileya@google.com static SkBitmapCache* gCache; 523589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // each cache cost 1K of RAM, since each bitmap will be 1x256 at 32bpp 524589708bf7c706348b763e8277004cb160b202bdbrileya@google.com static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; 525589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkAutoMutexAcquire ama(gMutex); 526589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 527589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (NULL == gCache) { 528589708bf7c706348b763e8277004cb160b202bdbrileya@google.com gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); 529589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 530589708bf7c706348b763e8277004cb160b202bdbrileya@google.com size_t size = count * sizeof(int32_t); 531589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 532589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (!gCache->find(storage.get(), size, bitmap)) { 533589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // force our cahce32pixelref to be built 534589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)this->getCache32(); 535589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Only expose the linear section of the cache; don't let the caller 536589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // know about the padding at the end to make interpolation faster. 537589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bitmap->setConfig(SkBitmap::kARGB_8888_Config, kGradient32Length, 1); 538589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bitmap->setPixelRef(fCache32PixelRef); 539589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 540589708bf7c706348b763e8277004cb160b202bdbrileya@google.com gCache->add(storage.get(), size, *bitmap); 541589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 542589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 543589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 544589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { 545589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info) { 546589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info->fColorCount >= fColorCount) { 547589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info->fColors) { 548589708bf7c706348b763e8277004cb160b202bdbrileya@google.com memcpy(info->fColors, fOrigColors, 549589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fColorCount * sizeof(SkColor)); 550589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 551589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info->fColorOffsets) { 552589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fColorCount == 2) { 553589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fColorOffsets[0] = 0; 554589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fColorOffsets[1] = SK_Scalar1; 555589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else if (fColorCount > 2) { 556589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < fColorCount; i++) 557589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos); 558589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 559589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 560589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 561589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fColorCount = fColorCount; 562589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fTileMode = fTileMode; 563589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 564589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 565589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 566589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/////////////////////////////////////////////////////////////////////////////// 567589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/////////////////////////////////////////////////////////////////////////////// 568589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 569589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkEmptyShader.h" 570589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 571589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// assumes colors is SkColor* and pos is SkScalar* 572589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define EXPAND_1_COLOR(count) \ 573589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkColor tmp[2]; \ 574589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { \ 575589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (1 == count) { \ 576589708bf7c706348b763e8277004cb160b202bdbrileya@google.com tmp[0] = tmp[1] = colors[0]; \ 577589708bf7c706348b763e8277004cb160b202bdbrileya@google.com colors = tmp; \ 578589708bf7c706348b763e8277004cb160b202bdbrileya@google.com pos = NULL; \ 579589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count = 2; \ 580589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } \ 581589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (0) 582589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 583589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader* SkGradientShader::CreateLinear(const SkPoint pts[2], 584589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkColor colors[], 585589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkScalar pos[], int colorCount, 586589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkShader::TileMode mode, 587589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkUnitMapper* mapper) { 588589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (NULL == pts || NULL == colors || colorCount < 1) { 589589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return NULL; 590589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 591589708bf7c706348b763e8277004cb160b202bdbrileya@google.com EXPAND_1_COLOR(colorCount); 592589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 593589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkNEW_ARGS(SkLinearGradient, 594589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (pts, colors, pos, colorCount, mode, mapper)); 595589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 596589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 597589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, 598589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkColor colors[], 599589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkScalar pos[], int colorCount, 600589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkShader::TileMode mode, 601589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkUnitMapper* mapper) { 602589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (radius <= 0 || NULL == colors || colorCount < 1) { 603589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return NULL; 604589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 605589708bf7c706348b763e8277004cb160b202bdbrileya@google.com EXPAND_1_COLOR(colorCount); 606589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 607589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkNEW_ARGS(SkRadialGradient, 608589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (center, radius, colors, pos, colorCount, mode, mapper)); 609589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 610589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 611589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, 612589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar startRadius, 613589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPoint& end, 614589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar endRadius, 615589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkColor colors[], 616589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkScalar pos[], 617589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int colorCount, 618589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkShader::TileMode mode, 619589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkUnitMapper* mapper) { 620589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { 621589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return NULL; 622589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 623589708bf7c706348b763e8277004cb160b202bdbrileya@google.com EXPAND_1_COLOR(colorCount); 624589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 625589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkNEW_ARGS(SkTwoPointRadialGradient, 626589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (start, startRadius, end, endRadius, colors, pos, 627589708bf7c706348b763e8277004cb160b202bdbrileya@google.com colorCount, mode, mapper)); 628589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 629589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 630589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, 631589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar startRadius, 632589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPoint& end, 633589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar endRadius, 634589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkColor colors[], 635589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkScalar pos[], 636589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int colorCount, 637589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkShader::TileMode mode, 638589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkUnitMapper* mapper) { 639589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { 640589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return NULL; 641589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 642589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (start == end && startRadius == endRadius) { 643589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkNEW(SkEmptyShader); 644589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 645589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 646589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkNEW_ARGS(SkTwoPointConicalGradient, 647589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (start, startRadius, end, endRadius, colors, pos, 648589708bf7c706348b763e8277004cb160b202bdbrileya@google.com colorCount, mode, mapper)); 649589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 650589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 651589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, 652589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkColor colors[], 653589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkScalar pos[], 654589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count, SkUnitMapper* mapper) { 655589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (NULL == colors || count < 1) { 656589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return NULL; 657589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 658589708bf7c706348b763e8277004cb160b202bdbrileya@google.com EXPAND_1_COLOR(count); 659589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 660589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkNEW_ARGS(SkSweepGradient, (cx, cy, colors, pos, count, mapper)); 661589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 662589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 663589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) 664589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) 665589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) 666589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) 667589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient) 668589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) 669589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 670d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 671d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com/////////////////////////////////////////////////////////////////////////////// 672d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 673d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comGrGLGradientStage::GrGLGradientStage(const GrProgramStageFactory& factory) 674d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com : INHERITED(factory) { } 675d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 676d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comGrGLGradientStage::~GrGLGradientStage() { } 677d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 678d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comvoid GrGLGradientStage::emitColorLookup(GrGLShaderBuilder* builder, 679d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const char* tName, 680d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const char* outputColor, 681d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const char* samplerName) { 682d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // Texture is effectively 1D so the y coordinate is 0.5, if we pack multiple 683d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // gradients into a texture, we could instead pick the appropriate row here 684d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com builder->fSampleCoords.printf("vec2(%s, 0.5)", tName); 685d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com builder->fComplexCoord = true; 686d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com builder->emitDefaultFetch(outputColor, samplerName); 687d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 688d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 689d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 690d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 691d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comGrGradientEffect::GrGradientEffect(GrTexture* texture) 692d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com : fTexture (texture) 693d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com , fUseTexture(true) { 694d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com SkSafeRef(fTexture); 695d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 696d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 697d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comGrGradientEffect::GrGradientEffect(GrContext* ctx, 698d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const SkShader& shader, 699d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com GrSamplerState* sampler) 700d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com : fTexture (NULL) 701d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com , fUseTexture (false) { 702d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // TODO: check for simple cases where we don't need a texture: 703d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com //GradientInfo info; 704d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com //shader.asAGradient(&info); 705d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com //if (info.fColorCount == 2) { ... 706d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 707d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com SkBitmap bitmap; 708d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com shader.asABitmap(&bitmap, NULL, NULL); 709d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 710d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com GrContext::TextureCacheEntry entry = GrLockCachedBitmapTexture(ctx, bitmap, 711d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com sampler->textureParams()); 712d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fTexture = entry.texture(); 713d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com SkSafeRef(fTexture); 714d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fUseTexture = true; 715d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 716d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // Unlock immediately, this is not great, but we don't have a way of 717d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // knowing when else to unlock it currently, so it may get purged from 718d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // the cache, but it'll still be ref'd until it's no longer being used. 719d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com GrUnlockCachedBitmapTexture(ctx, entry); 720d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 721d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 722d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comGrGradientEffect::~GrGradientEffect() { 723d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com SkSafeUnref(fTexture); 724d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 725d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 726d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comunsigned int GrGradientEffect::numTextures() const { 727d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com return fUseTexture ? 1 : 0; 728d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 729d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 730d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comGrTexture* GrGradientEffect::texture(unsigned int index) 731d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const { 732d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com GrAssert(fUseTexture && 0 == index); 733d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com return fTexture; 734d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 735d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 736