1589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 2589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Copyright 2012 Google Inc. 3589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * 4589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Use of this source code is governed by a BSD-style license that can be 5589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * found in the LICENSE file. 6589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 7589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 8589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkLinearGradient.h" 9589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 10589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline int repeat_bits(int x, const int bits) { 11589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return x & ((1 << bits) - 1); 12589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 13589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 14589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline int repeat_8bits(int x) { 15589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return x & 0xFF; 16589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 17589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 18589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly. 19589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// See http://code.google.com/p/skia/issues/detail?id=472 20589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#if defined(_MSC_VER) && (_MSC_VER >= 1600) 21589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#pragma optimize("", off) 22589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#endif 23589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 24589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline int mirror_bits(int x, const int bits) { 2538bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org if (x & (1 << bits)) { 26589708bf7c706348b763e8277004cb160b202bdbrileya@google.com x = ~x; 2738bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org } 28589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return x & ((1 << bits) - 1); 29589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 30589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 31589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic inline int mirror_8bits(int x) { 32589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (x & 256) { 33589708bf7c706348b763e8277004cb160b202bdbrileya@google.com x = ~x; 34589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 35589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return x & 255; 36589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 37589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 38589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#if defined(_MSC_VER) && (_MSC_VER >= 1600) 39589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#pragma optimize("", on) 40589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#endif 41589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 42589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic void pts_to_unit_matrix(const SkPoint pts[2], SkMatrix* matrix) { 43589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkVector vec = pts[1] - pts[0]; 44589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar mag = vec.length(); 45589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar inv = mag ? SkScalarInvert(mag) : 0; 46589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 47589708bf7c706348b763e8277004cb160b202bdbrileya@google.com vec.scale(inv); 48589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); 49589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->postTranslate(-pts[0].fX, -pts[0].fY); 50589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->postScale(inv, inv); 51589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 52589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 53589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/////////////////////////////////////////////////////////////////////////////// 54589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 559c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.orgSkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc, 569c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org const SkMatrix* localMatrix) 579c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org : SkGradientShaderBase(desc, localMatrix) 58589708bf7c706348b763e8277004cb160b202bdbrileya@google.com , fStart(pts[0]) 59589708bf7c706348b763e8277004cb160b202bdbrileya@google.com , fEnd(pts[1]) { 60589708bf7c706348b763e8277004cb160b202bdbrileya@google.com pts_to_unit_matrix(pts, &fPtsToUnit); 61589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 62589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 638b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkLinearGradient::SkLinearGradient(SkReadBuffer& buffer) 64589708bf7c706348b763e8277004cb160b202bdbrileya@google.com : INHERITED(buffer) 65589708bf7c706348b763e8277004cb160b202bdbrileya@google.com , fStart(buffer.readPoint()) 66589708bf7c706348b763e8277004cb160b202bdbrileya@google.com , fEnd(buffer.readPoint()) { 67589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 68589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 698b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLinearGradient::flatten(SkWriteBuffer& buffer) const { 70589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->INHERITED::flatten(buffer); 71589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writePoint(fStart); 72589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writePoint(fEnd); 73589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 74589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 7587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkLinearGradient::contextSize() const { 7687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(LinearGradientContext); 7787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 7887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 79ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void* storage) const { 80e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, LinearGradientContext, (*this, rec)); 8187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 8287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 8387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkLinearGradient::LinearGradientContext::LinearGradientContext( 84e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkLinearGradient& shader, const ContextRec& rec) 85e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) 8687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{ 87589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; 88589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((fDstToIndex.getType() & ~mask) == 0) { 8960040292be58ac553298209fb2e0684a4cb17dccreed@google.com // when we dither, we are (usually) not const-in-Y 90e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org if ((fFlags & SkShader::kHasSpan16_Flag) && !rec.fPaint->isDither()) { 91589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // only claim this if we do have a 16bit mode (i.e. none of our 92589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // colors have alpha), and if we are not dithering (which obviously 93589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // is not const in Y). 94589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fFlags |= SkShader::kConstInY16_Flag; 95589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 96589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 97589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 98589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 99589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define NO_CHECK_ITER \ 100589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { \ 101589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = fx >> SkGradientShaderBase::kCache32Shift; \ 102589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFF); \ 103589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; \ 104589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + fi]; \ 10555853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); \ 106589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (0) 107589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 108589708bf7c706348b763e8277004cb160b202bdbrileya@google.comnamespace { 109589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 110589708bf7c706348b763e8277004cb160b202bdbrileya@google.comtypedef void (*LinearShadeProc)(TileProc proc, SkFixed dx, SkFixed fx, 111589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* dstC, const SkPMColor* cache, 112589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count); 113589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 114589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Linear interpolation (lerp) is unnecessary if there are no sharp 115589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// discontinuities in the gradient - which must be true if there are 116589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// only 2 colors - but it's cheap. 117589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_linear_vertical_lerp(TileProc proc, SkFixed dx, SkFixed fx, 118589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, 119589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPMColor* SK_RESTRICT cache, 120589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 121589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // We're a vertical gradient, so no change in a span. 122589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // If colors change sharply across the gradient, dithering is 123589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // insufficient (it subsamples the color space) and we need to lerp. 124589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fullIndex = proc(fx); 1253c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com unsigned fi = fullIndex >> SkGradientShaderBase::kCache32Shift; 1263c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com unsigned remainder = fullIndex & ((1 << SkGradientShaderBase::kCache32Shift) - 1); 1279dde018753c4d16cdc60c008c32bb0b573a82944skia.committer@gmail.com 1283c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com int index0 = fi + toggle; 1293c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com int index1 = index0; 1303c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com if (fi < SkGradientShaderBase::kCache32Count - 1) { 1313c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com index1 += 1; 1323c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com } 1333c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com SkPMColor lerp = SkFastFourByteInterp(cache[index1], cache[index0], remainder); 1343c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com index0 ^= SkGradientShaderBase::kDitherStride32; 1353c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com index1 ^= SkGradientShaderBase::kDitherStride32; 1363c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com SkPMColor dlerp = SkFastFourByteInterp(cache[index1], cache[index0], remainder); 137589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_memset32_dither(dstC, lerp, dlerp, count); 138589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 139589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 140589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx, 141589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, 142589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPMColor* SK_RESTRICT cache, 143589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 144589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkClampRange range; 1453c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1); 146589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 147589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count = range.fCount0) > 0) { 148589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_memset32_dither(dstC, 149589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[toggle + range.fV0], 15055853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle(toggle) + range.fV0], 151589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count); 152589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstC += count; 153589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 154589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count = range.fCount1) > 0) { 155589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int unroll = count >> 3; 156589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx = range.fFx1; 157589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < unroll; i++) { 158589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER; NO_CHECK_ITER; 159589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER; NO_CHECK_ITER; 160589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER; NO_CHECK_ITER; 161589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER; NO_CHECK_ITER; 162589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 163589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count &= 7) > 0) { 164589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 165589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER; 166589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 167589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 168589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 169589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count = range.fCount2) > 0) { 170589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_memset32_dither(dstC, 171589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[toggle + range.fV1], 17255853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle(toggle) + range.fV1], 173589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count); 174589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 175589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 176589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 177589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_linear_mirror(TileProc proc, SkFixed dx, SkFixed fx, 178589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, 179589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPMColor* SK_RESTRICT cache, 180589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 181589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 182589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = mirror_8bits(fx >> 8); 183589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFF); 184589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 185589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + fi]; 18655853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 187589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 188589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 189589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 190589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_linear_repeat(TileProc proc, SkFixed dx, SkFixed fx, 191589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, 192589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const SkPMColor* SK_RESTRICT cache, 193589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 194589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 195589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = repeat_8bits(fx >> 8); 196589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFF); 197589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 198589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + fi]; 19955853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 200589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 201589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 202589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 203589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 204589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 20587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, 20687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int count) { 207589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 208589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 20987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient&>(fShader); 21087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 211589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 212589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 21387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = linearGradient.fTileProc; 21487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); 21555853db3cce9539746fe202519a534c85ecdf62creed@google.com int toggle = init_dither_toggle(x, y); 216589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 217589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 218589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 219589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 220589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dx, fx = SkScalarToFixed(srcPt.fX); 221589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 222589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 223589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dxStorage[1]; 224589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL); 225589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dx = dxStorage[0]; 226589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 227589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 228589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dx = SkScalarToFixed(fDstToIndex.getScaleX()); 229589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 230589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 231589708bf7c706348b763e8277004cb160b202bdbrileya@google.com LinearShadeProc shadeProc = shadeSpan_linear_repeat; 23253009ba7019cbe86a6ab2aa5b7ae5893e4efffbdreed@google.com if (0 == dx) { 233589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_linear_vertical_lerp; 23487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) { 235589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_linear_clamp; 23687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) { 237589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_linear_mirror; 238589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 23987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode); 240589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 241589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(proc, dx, fx, dstC, cache, toggle, count); 242589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 243589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 244589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 245589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 246589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 247589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(SkScalarToFixed(srcPt.fX)); 248589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 249589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (fi >> kCache32Shift)]; 25055853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 251589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 252589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 253589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 254589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 255589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 256589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::BitmapType SkLinearGradient::asABitmap(SkBitmap* bitmap, 257589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix* matrix, 258589708bf7c706348b763e8277004cb160b202bdbrileya@google.com TileMode xy[]) const { 259589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (bitmap) { 2601c6d64b78b24083ee9fd7411dac8a4a7e2d03a3crileya@google.com this->getGradientTableBitmap(bitmap); 261589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 262589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (matrix) { 263589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->preConcat(fPtsToUnit); 264589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 265589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (xy) { 266589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[0] = fTileMode; 267589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[1] = kClamp_TileMode; 268589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 269589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kLinear_BitmapType; 270589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 271589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 272589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const { 273589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info) { 274589708bf7c706348b763e8277004cb160b202bdbrileya@google.com commonAsAGradient(info); 275589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fPoint[0] = fStart; 276589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fPoint[1] = fEnd; 277589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 278589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kLinear_GradientType; 279589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 280589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 281589708bf7c706348b763e8277004cb160b202bdbrileya@google.comstatic void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, 282589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count) { 283589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (reinterpret_cast<uintptr_t>(dst) & 2) { 284589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dst++ = value; 285589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count -= 1; 286589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkTSwap(value, other); 287589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 288589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 289589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1); 290589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 291589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (count & 1) { 292589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dst[count - 1] = value; 293589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 294589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 295589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 296589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define NO_CHECK_ITER_16 \ 297589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { \ 298589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = fx >> SkGradientShaderBase::kCache16Shift; \ 299589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi < SkGradientShaderBase::kCache16Count); \ 300589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; \ 301589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + fi]; \ 30255853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); \ 303589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (0) 304589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 305589708bf7c706348b763e8277004cb160b202bdbrileya@google.comnamespace { 306589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 307589708bf7c706348b763e8277004cb160b202bdbrileya@google.comtypedef void (*LinearShade16Proc)(TileProc proc, SkFixed dx, SkFixed fx, 308589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* dstC, const uint16_t* cache, 309589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count); 310589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 311589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan16_linear_vertical(TileProc proc, SkFixed dx, SkFixed fx, 312589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC, 313589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint16_t* SK_RESTRICT cache, 314589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 315589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // we're a vertical gradient, so no change in a span 316589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(fx) >> SkGradientShaderBase::kCache16Shift; 317589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi < SkGradientShaderBase::kCache16Count); 318589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dither_memset16(dstC, cache[toggle + fi], 31955853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle16(toggle) + fi], count); 320589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 321589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 322589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan16_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx, 323589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC, 324589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint16_t* SK_RESTRICT cache, 325589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 326589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkClampRange range; 3273c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1); 328589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 329589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count = range.fCount0) > 0) { 330589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dither_memset16(dstC, 331589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[toggle + range.fV0], 33255853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle16(toggle) + range.fV0], 333589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count); 334589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstC += count; 335589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 336589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count = range.fCount1) > 0) { 337589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int unroll = count >> 3; 338589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx = range.fFx1; 339589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < unroll; i++) { 340589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER_16; NO_CHECK_ITER_16; 341589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER_16; NO_CHECK_ITER_16; 342589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER_16; NO_CHECK_ITER_16; 343589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER_16; NO_CHECK_ITER_16; 344589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 345589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count &= 7) > 0) { 346589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 347589708bf7c706348b763e8277004cb160b202bdbrileya@google.com NO_CHECK_ITER_16; 348589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 349589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 350589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 351589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count = range.fCount2) > 0) { 352589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dither_memset16(dstC, 353589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[toggle + range.fV1], 35455853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle16(toggle) + range.fV1], 355589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count); 356589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 357589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 358589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 359589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan16_linear_mirror(TileProc proc, SkFixed dx, SkFixed fx, 360589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC, 361589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint16_t* SK_RESTRICT cache, 362589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 363589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 364589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = mirror_bits(fx >> SkGradientShaderBase::kCache16Shift, 365589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkGradientShaderBase::kCache16Bits); 366589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi < SkGradientShaderBase::kCache16Count); 367589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 368589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + fi]; 36955853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 370589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 371589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 372589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 373589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan16_linear_repeat(TileProc proc, SkFixed dx, SkFixed fx, 374589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC, 375589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint16_t* SK_RESTRICT cache, 376589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 377589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 378589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = repeat_bits(fx >> SkGradientShaderBase::kCache16Shift, 379589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkGradientShaderBase::kCache16Bits); 380589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi < SkGradientShaderBase::kCache16Count); 381589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 382589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + fi]; 38355853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 384589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 385589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 386589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 387589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 3881915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.comstatic bool fixed_nearly_zero(SkFixed x) { 3891915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com return SkAbs32(x) < (SK_Fixed1 >> 12); 3901915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com} 3911915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com 39287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y, 39387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org uint16_t* SK_RESTRICT dstC, int count) { 394589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 395589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 39687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient&>(fShader); 39787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 398589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 399589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 40087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = linearGradient.fTileProc; 40187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const uint16_t* SK_RESTRICT cache = fCache->getCache16(); 40255853db3cce9539746fe202519a534c85ecdf62creed@google.com int toggle = init_dither_toggle16(x, y); 403589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 404589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 405589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 406589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 407589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dx, fx = SkScalarToFixed(srcPt.fX); 408589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 409589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 410589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dxStorage[1]; 411589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL); 412589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dx = dxStorage[0]; 413589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 414589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 415589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dx = SkScalarToFixed(fDstToIndex.getScaleX()); 416589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 417589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 418589708bf7c706348b763e8277004cb160b202bdbrileya@google.com LinearShade16Proc shadeProc = shadeSpan16_linear_repeat; 4191915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com if (fixed_nearly_zero(dx)) { 420589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_linear_vertical; 42187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) { 422589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_linear_clamp; 42387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) { 424589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_linear_mirror; 425589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 42687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode); 427589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 428589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(proc, dx, fx, dstC, cache, toggle, count); 429589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 430589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 431589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 432589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 433589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 434589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(SkScalarToFixed(srcPt.fX)); 435589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 436589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 437589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int index = fi >> kCache16Shift; 438589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + index]; 43955853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 440589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 441589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 442589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 443589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 444589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 445589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 446cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 447cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 4482eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "GrTBackendEffectFactory.h" 4499de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#include "SkGr.h" 4502eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com 451d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 452d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4530707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.comclass GrGLLinearGradient : public GrGLGradientEffect { 454d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.compublic: 455d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 456c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com GrGLLinearGradient(const GrBackendEffectFactory& factory, const GrDrawEffect&) 457d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com : INHERITED (factory) { } 458d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 459d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com virtual ~GrGLLinearGradient() { } 460d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 461f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com virtual void emitCode(GrGLShaderBuilder*, 462c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com const GrDrawEffect&, 463f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com EffectKey, 464f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 465f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 46677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 467f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 468f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com 469c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com static EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 47082d1223aece4703bc9f3a3612cbabaa8c2f2809bbsalomon@google.com return GenBaseGradientKey(drawEffect); 471d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com } 472d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 473d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comprivate: 474d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4750707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.com typedef GrGLGradientEffect INHERITED; 476d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com}; 477d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 47898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 47998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 48098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comclass GrLinearGradient : public GrGradientEffect { 48198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.compublic: 48298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 4830ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com static GrEffectRef* Create(GrContext* ctx, 4840ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkLinearGradient& shader, 4850ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkMatrix& matrix, 4860ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com SkShader::TileMode tm) { 4876340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com AutoEffectUnref effect(SkNEW_ARGS(GrLinearGradient, (ctx, shader, matrix, tm))); 488a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com return CreateEffectRef(effect); 4890ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 4900ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 49198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com virtual ~GrLinearGradient() { } 49298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 49398e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com static const char* Name() { return "Linear Gradient"; } 494396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 495396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com return GrTBackendEffectFactory<GrLinearGradient>::getInstance(); 49698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 49798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 498422e81aeb1f4078367c85efe591c7df8c33874ecbsalomon@google.com typedef GrGLLinearGradient GLEffect; 49998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comprivate: 5010ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrLinearGradient(GrContext* ctx, 5020ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkLinearGradient& shader, 5030ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkMatrix& matrix, 5040ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com SkShader::TileMode tm) 5050ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com : INHERITED(ctx, shader, matrix, tm) { } 506f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com GR_DECLARE_EFFECT_TEST; 50798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com typedef GrGradientEffect INHERITED; 50998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com}; 51098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 51198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 51298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 513f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrLinearGradient); 514d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 515e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgGrEffectRef* GrLinearGradient::TestCreate(SkRandom* random, 5160ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrContext* context, 517c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com const GrDrawTargetCaps&, 5180ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrTexture**) { 519d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkPoint points[] = {{random->nextUScalar1(), random->nextUScalar1()}, 520d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com {random->nextUScalar1(), random->nextUScalar1()}}; 521d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 522d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkColor colors[kMaxRandomGradientColors]; 523d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar stopsArray[kMaxRandomGradientColors]; 524d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar* stops = stopsArray; 525d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkShader::TileMode tm; 526d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com int colorCount = RandomGradientParams(random, colors, &stops, &tm); 527d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkAutoTUnref<SkShader> shader(SkGradientShader::CreateLinear(points, 528d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com colors, stops, colorCount, 529d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com tm)); 530e197cbf9a3e66bab926bc5e51962752dad5221a0bsalomon@google.com SkPaint paint; 5319de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrColor grColor; 5329de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrEffectRef* effect; 5339de5b514d38c5b36066bcdc14fba2f7e5196d372dandov shader->asNewEffect(context, paint, NULL, &grColor, &effect); 5349de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return effect; 535d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com} 536d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 537d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com///////////////////////////////////////////////////////////////////// 538d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 539f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.comvoid GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder, 540c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com const GrDrawEffect&, 541d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com EffectKey key, 542f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 543f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 54477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 545f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray& samplers) { 54682d1223aece4703bc9f3a3612cbabaa8c2f2809bbsalomon@google.com this->emitUniforms(builder, key); 54777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com SkString t = builder->ensureFSCoords2D(coords, 0); 548d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com t.append(".x"); 54982d1223aece4703bc9f3a3612cbabaa8c2f2809bbsalomon@google.com this->emitColor(builder, t.c_str(), key, outputColor, inputColor, samplers); 550d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 551d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 552d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 553d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 5549de5b514d38c5b36066bcdc14fba2f7e5196d372dandovbool SkLinearGradient::asNewEffect(GrContext* context, const SkPaint& paint, 5559de5b514d38c5b36066bcdc14fba2f7e5196d372dandov const SkMatrix* localMatrix, GrColor* grColor, 5569de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrEffectRef** grEffect) const { 55700835cc55046e66b5a33633ec045bc9aa0015ebdbsalomon@google.com SkASSERT(NULL != context); 5589de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 559dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com SkMatrix matrix; 560f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com if (!this->getLocalMatrix().invert(&matrix)) { 5619de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 562dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com } 56396fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (localMatrix) { 56496fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org SkMatrix inv; 56596fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (!localMatrix->invert(&inv)) { 5669de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 56796fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 56896fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org matrix.postConcat(inv); 56996fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 570f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com matrix.postConcat(fPtsToUnit); 5719de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 5729de5b514d38c5b36066bcdc14fba2f7e5196d372dandov *grColor = SkColor2GrColorJustAlpha(paint.getColor()); 5739de5b514d38c5b36066bcdc14fba2f7e5196d372dandov *grEffect = GrLinearGradient::Create(context, *this, matrix, fTileMode); 5749de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 5759de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 576d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 577d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 578cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 579cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 5809de5b514d38c5b36066bcdc14fba2f7e5196d372dandovbool SkLinearGradient::asNewEffect(GrContext* context, const SkPaint& paint, 5819de5b514d38c5b36066bcdc14fba2f7e5196d372dandov const SkMatrix* localMatrix, GrColor* grColor, 5829de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrEffectRef** grEffect) const { 583cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 5849de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 585cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com} 586cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 587cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 58876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 5890f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 59076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkLinearGradient::toString(SkString* str) const { 59176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkLinearGradient ("); 59276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 59376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendf("start: (%f, %f)", fStart.fX, fStart.fY); 59476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendf(" end: (%f, %f) ", fEnd.fX, fEnd.fY); 59576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 59676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 59776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 59876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 59976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 60076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 601