1589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 3589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Copyright 2012 Google Inc. 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 "SkRadialGradient.h" 10589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "SkRadialGradient_Table.h" 11589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 12589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define kSQRT_TABLE_BITS 11 13589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define kSQRT_TABLE_SIZE (1 << kSQRT_TABLE_BITS) 14589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 154ec5c95bc514e15f726ee5c3b83e1578e3d00d13reed@google.com#if 0 16589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 17589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include <stdio.h> 18589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 19589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkRadialGradient_BuildTable() { 20589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // build it 0..127 x 0..127, so we use 2^15 - 1 in the numerator for our "fixed" table 21589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 22589708bf7c706348b763e8277004cb160b202bdbrileya@google.com FILE* file = ::fopen("SkRadialGradient_Table.h", "w"); 23589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(file); 24589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fprintf(file, "static const uint8_t gSqrt8Table[] = {\n"); 25589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 26589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (int i = 0; i < kSQRT_TABLE_SIZE; i++) { 27589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((i & 15) == 0) { 28589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fprintf(file, "\t"); 29589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 30589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 31589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint8_t value = SkToU8(SkFixedSqrt(i * SK_Fixed1 / kSQRT_TABLE_SIZE) >> 8); 32589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 33589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fprintf(file, "0x%02X", value); 34589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (i < kSQRT_TABLE_SIZE-1) { 35589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fprintf(file, ", "); 36589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 37589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((i & 15) == 15) { 38589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fprintf(file, "\n"); 39589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 40589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 41589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fprintf(file, "};\n"); 42589708bf7c706348b763e8277004cb160b202bdbrileya@google.com ::fclose(file); 43589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 44589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 45589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#endif 46589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 47589708bf7c706348b763e8277004cb160b202bdbrileya@google.comnamespace { 48589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 4934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org// GCC doesn't like using static functions as template arguments. So force these to be non-static. 5034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orginline SkFixed mirror_tileproc_nonstatic(SkFixed x) { 5134150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org return mirror_tileproc(x); 5234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} 5334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 5434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orginline SkFixed repeat_tileproc_nonstatic(SkFixed x) { 5534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org return repeat_tileproc(x); 5634150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} 5734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 58589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid rad_to_unit_matrix(const SkPoint& center, SkScalar radius, 59589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix* matrix) { 60589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar inv = SkScalarInvert(radius); 61589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 62589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->setTranslate(-center.fX, -center.fY); 63589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->postScale(inv, inv); 64589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 65589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 66589708bf7c706348b763e8277004cb160b202bdbrileya@google.comtypedef void (* RadialShade16Proc)(SkScalar sfx, SkScalar sdx, 67589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sfy, SkScalar sdy, 68589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* dstC, const uint16_t* cache, 69589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count); 70589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 71589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan16_radial_clamp(SkScalar sfx, SkScalar sdx, 72589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sfy, SkScalar sdy, 73589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache, 74589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int toggle, int count) { 75589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table; 76589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 77589708bf7c706348b763e8277004cb160b202bdbrileya@google.com /* knock these down so we can pin against +- 0x7FFF, which is an 78589708bf7c706348b763e8277004cb160b202bdbrileya@google.com immediate load, rather than 0xFFFF which is slower. This is a 79589708bf7c706348b763e8277004cb160b202bdbrileya@google.com compromise, since it reduces our precision, but that appears 80589708bf7c706348b763e8277004cb160b202bdbrileya@google.com to be visually OK. If we decide this is OK for all of our cases, 81589708bf7c706348b763e8277004cb160b202bdbrileya@google.com we could (it seems) put this scale-down into fDstToIndex, 82589708bf7c706348b763e8277004cb160b202bdbrileya@google.com to avoid having to do these extra shifts each time. 83589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 84589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fx = SkScalarToFixed(sfx) >> 1; 85589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dx = SkScalarToFixed(sdx) >> 1; 86589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fy = SkScalarToFixed(sfy) >> 1; 87589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dy = SkScalarToFixed(sdy) >> 1; 88589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // might perform this check for the other modes, 89589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // but the win will be a smaller % of the total 90589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (dy == 0) { 91589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); 92589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy *= fy; 93589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 94589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); 95589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS); 96589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); 97589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 98589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + 99589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (sqrt_table[fi] >> SkGradientShaderBase::kSqrt16Shift)]; 10055853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 101589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 102589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 103589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 104589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); 105589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); 106589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS); 107589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); 108589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 109589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 110589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + 111589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (sqrt_table[fi] >> SkGradientShaderBase::kSqrt16Shift)]; 11255853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 113589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 114589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 115589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 116589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 11734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgtemplate <SkFixed (*TileProc)(SkFixed)> 11834150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan16_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 11934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache, 12034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int toggle, int count) { 121589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 12234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy)); 12334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org const unsigned fi = TileProc(dist); 124589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 125589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache16Shift)]; 12655853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 127589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 128589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 129589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 130589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 131589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 13234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan16_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 13334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache, 13434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int toggle, int count) { 13534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org shadeSpan16_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, toggle, count); 13634150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} 13734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 13834150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan16_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 13934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache, 14034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int toggle, int count) { 14134150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org shadeSpan16_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, toggle, count); 142589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 143589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 14434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} // namespace 14534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 14698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 14798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 148589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius, 1499c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org const Descriptor& desc, const SkMatrix* localMatrix) 1509c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org : SkGradientShaderBase(desc, localMatrix), 151589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCenter(center), 152589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fRadius(radius) 153589708bf7c706348b763e8277004cb160b202bdbrileya@google.com{ 154589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // make sure our table is insync with our current #define for kSQRT_TABLE_SIZE 155589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE); 156589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 157589708bf7c706348b763e8277004cb160b202bdbrileya@google.com rad_to_unit_matrix(center, radius, &fPtsToUnit); 158589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 159589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 16087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkRadialGradient::contextSize() const { 16187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(RadialGradientContext); 16287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 16387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 164ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkRadialGradient::onCreateContext(const ContextRec& rec, void* storage) const { 165e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, rec)); 16687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 16787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 16887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkRadialGradient::RadialGradientContext::RadialGradientContext( 169e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkRadialGradient& shader, const ContextRec& rec) 170e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) {} 17187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 17287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkRadialGradient::RadialGradientContext::shadeSpan16(int x, int y, uint16_t* dstCParam, 17387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int count) { 174589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 175589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 17687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader); 17787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 178589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC = dstCParam; 179589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 180589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 181589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 18287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = radialGradient.fTileProc; 18387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const uint16_t* SK_RESTRICT cache = fCache->getCache16(); 18455853db3cce9539746fe202519a534c85ecdf62creed@google.com int toggle = init_dither_toggle16(x, y); 185589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 186589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 187589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 188589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 189589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 190589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdx = fDstToIndex.getScaleX(); 191589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdy = fDstToIndex.getSkewY(); 192589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 193589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 194589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed storage[2]; 195589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), 196589708bf7c706348b763e8277004cb160b202bdbrileya@google.com &storage[0], &storage[1]); 197589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdx = SkFixedToScalar(storage[0]); 198589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdy = SkFixedToScalar(storage[1]); 199589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 200589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 201589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 202589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 203589708bf7c706348b763e8277004cb160b202bdbrileya@google.com RadialShade16Proc shadeProc = shadeSpan16_radial_repeat; 20487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { 205589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_radial_clamp; 20687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { 207589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_radial_mirror; 208589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 20987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); 210589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 211589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, 212589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache, toggle, count); 213589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { // perspective case 214589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 215589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 216589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 217589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 218589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(SkScalarToFixed(srcPt.length())); 219589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 220589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 221589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int index = fi >> (16 - kCache16Bits); 222589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + index]; 22355853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 224589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 225589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 226589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 227589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 228589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 229589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 230fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comSkShader::BitmapType SkRadialGradient::asABitmap(SkBitmap* bitmap, 231589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix* matrix, SkShader::TileMode* xy) const { 232589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (bitmap) { 2331c6d64b78b24083ee9fd7411dac8a4a7e2d03a3crileya@google.com this->getGradientTableBitmap(bitmap); 234589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 235589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (matrix) { 2363c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com matrix->setScale(SkIntToScalar(kCache32Count), 2373c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com SkIntToScalar(kCache32Count)); 238589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->preConcat(fPtsToUnit); 239589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 240589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (xy) { 241589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[0] = fTileMode; 242589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[1] = kClamp_TileMode; 243589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 244589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kRadial_BitmapType; 245589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 246589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 247589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::GradientType SkRadialGradient::asAGradient(GradientInfo* info) const { 248589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info) { 249589708bf7c706348b763e8277004cb160b202bdbrileya@google.com commonAsAGradient(info); 250589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fPoint[0] = fCenter; 251589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fRadius[0] = fRadius; 252589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 253589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kRadial_GradientType; 254589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 255589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2568b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkRadialGradient::SkRadialGradient(SkReadBuffer& buffer) 257589708bf7c706348b763e8277004cb160b202bdbrileya@google.com : INHERITED(buffer), 258589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCenter(buffer.readPoint()), 259589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fRadius(buffer.readScalar()) { 260589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 261589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2628b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkRadialGradient::flatten(SkWriteBuffer& buffer) const { 263589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->INHERITED::flatten(buffer); 264589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writePoint(fCenter); 265589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeScalar(fRadius); 266589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 267589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 268589708bf7c706348b763e8277004cb160b202bdbrileya@google.comnamespace { 269589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 270589708bf7c706348b763e8277004cb160b202bdbrileya@google.cominline bool radial_completely_pinned(int fx, int dx, int fy, int dy) { 271589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // fast, overly-conservative test: checks unit square instead 272589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // of unit circle 273589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bool xClamped = (fx >= SK_FixedHalf && dx >= 0) || 274589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (fx <= -SK_FixedHalf && dx <= 0); 275589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bool yClamped = (fy >= SK_FixedHalf && dy >= 0) || 276589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (fy <= -SK_FixedHalf && dy <= 0); 277589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 278589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return xClamped || yClamped; 279589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 280589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 281589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Return true if (fx * fy) is always inside the unit circle 282589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// SkPin32 is expensive, but so are all the SkFixedMul in this test, 283589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// so it shouldn't be run if count is small. 284589708bf7c706348b763e8277004cb160b202bdbrileya@google.cominline bool no_need_for_radial_pin(int fx, int dx, 285589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int fy, int dy, int count) { 286589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 287589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) { 288589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 289589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 290589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fx*fx + fy*fy > 0x7FFF*0x7FFF) { 291589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 292589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 293589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += (count - 1) * dx; 294589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += (count - 1) * dy; 295589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) { 296589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 297589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 298589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return fx*fx + fy*fy <= 0x7FFF*0x7FFF; 299589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 300589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 301589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define UNPINNED_RADIAL_STEP \ 302589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = (fx * fx + fy * fy) >> (14 + 16 - kSQRT_TABLE_BITS); \ 303589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + \ 304589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (sqrt_table[fi] >> SkGradientShaderBase::kSqrt32Shift)]; \ 30555853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); \ 306589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; \ 307589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 308589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 309589708bf7c706348b763e8277004cb160b202bdbrileya@google.comtypedef void (* RadialShadeProc)(SkScalar sfx, SkScalar sdx, 310589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sfy, SkScalar sdy, 311589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* dstC, const SkPMColor* cache, 312589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count, int toggle); 313589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 314589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// On Linux, this is faster with SkPMColor[] params than SkPMColor* SK_RESTRICT 315589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx, 316589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sfy, SkScalar sdy, 317589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 318589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count, int toggle) { 319589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Floating point seems to be slower than fixed point, 320589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // even when we have float hardware. 321589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table; 322589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fx = SkScalarToFixed(sfx) >> 1; 323589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dx = SkScalarToFixed(sdx) >> 1; 324589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fy = SkScalarToFixed(sfy) >> 1; 325589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dy = SkScalarToFixed(sdy) >> 1; 326589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) { 3273c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com unsigned fi = SkGradientShaderBase::kCache32Count - 1; 328589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_memset32_dither(dstC, 329589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[toggle + fi], 33055853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle(toggle) + fi], 331589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count); 332589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else if ((count > 4) && 333589708bf7c706348b763e8277004cb160b202bdbrileya@google.com no_need_for_radial_pin(fx, dx, fy, dy, count)) { 334589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi; 335589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // 4x unroll appears to be no faster than 2x unroll on Linux 336589708bf7c706348b763e8277004cb160b202bdbrileya@google.com while (count > 1) { 337589708bf7c706348b763e8277004cb160b202bdbrileya@google.com UNPINNED_RADIAL_STEP; 338589708bf7c706348b763e8277004cb160b202bdbrileya@google.com UNPINNED_RADIAL_STEP; 339589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count -= 2; 340589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 341589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (count) { 342589708bf7c706348b763e8277004cb160b202bdbrileya@google.com UNPINNED_RADIAL_STEP; 343589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 34460040292be58ac553298209fb2e0684a4cb17dccreed@google.com } else { 345589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Specializing for dy == 0 gains us 25% on Skia benchmarks 346589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (dy == 0) { 347589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned yy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); 348589708bf7c706348b763e8277004cb160b202bdbrileya@google.com yy *= yy; 349589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 350589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); 351589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = (xx * xx + yy) >> (14 + 16 - kSQRT_TABLE_BITS); 352589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); 353589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (sqrt_table[fi] >> 354589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkGradientShaderBase::kSqrt32Shift)]; 35555853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 356589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 357589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 358589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 359589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 360589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); 361589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); 362589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS); 363589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); 364589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (sqrt_table[fi] >> 365589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkGradientShaderBase::kSqrt32Shift)]; 36655853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 367589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 368589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 369589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 370589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 371589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 372589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 373589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 374589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Unrolling this loop doesn't seem to help (when float); we're stalling to 375589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// get the results of the sqrt (?), and don't have enough extra registers to 376589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// have many in flight. 37734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgtemplate <SkFixed (*TileProc)(SkFixed)> 37834150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 37934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 38034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int count, int toggle) { 381589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 38234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy)); 38334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org const unsigned fi = TileProc(dist); 384589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 385589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache32Shift)]; 38655853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 387589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 388589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 389589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 390589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 39134150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 39234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 39334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 39434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int count, int toggle) { 39534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org shadeSpan_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle); 39634150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} 39734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 39834150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 39934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 40034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int count, int toggle) { 40134150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org shadeSpan_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle); 402589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 403589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 40434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} // namespace 40534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 40687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y, 40787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, int count) { 408589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 409589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 41087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader); 41187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 412589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 413589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 41487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = radialGradient.fTileProc; 41587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); 41655853db3cce9539746fe202519a534c85ecdf62creed@google.com int toggle = init_dither_toggle(x, y); 417589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 418589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 419589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 420589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 421589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdx = fDstToIndex.getScaleX(); 422589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdy = fDstToIndex.getSkewY(); 423589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 424589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 425589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed storage[2]; 426589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), 427589708bf7c706348b763e8277004cb160b202bdbrileya@google.com &storage[0], &storage[1]); 428589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdx = SkFixedToScalar(storage[0]); 429589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdy = SkFixedToScalar(storage[1]); 430589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 431589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 432589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 433589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 434589708bf7c706348b763e8277004cb160b202bdbrileya@google.com RadialShadeProc shadeProc = shadeSpan_radial_repeat; 43587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { 436589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_radial_clamp; 43787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { 438589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_radial_mirror; 439589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 44087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); 441589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 442589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle); 443589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { // perspective case 444589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 445589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 446589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 447589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 448589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(SkScalarToFixed(srcPt.length())); 449589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 450589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[fi >> SkGradientShaderBase::kCache32Shift]; 451589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 452589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 453589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 454589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 455589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 456d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 457d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 458cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 459cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 4602eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "GrTBackendEffectFactory.h" 4619de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#include "SkGr.h" 4622eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com 4630707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.comclass GrGLRadialGradient : public GrGLGradientEffect { 464d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.compublic: 465d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 466396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com GrGLRadialGradient(const GrBackendEffectFactory& factory, 467c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com const GrDrawEffect&) : INHERITED (factory) { } 468d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com virtual ~GrGLRadialGradient() { } 469d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 470f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com virtual void emitCode(GrGLShaderBuilder*, 471c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com const GrDrawEffect&, 472f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com EffectKey, 473f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 474f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 47577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 476f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 477d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 478c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com static EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 47982d1223aece4703bc9f3a3612cbabaa8c2f2809bbsalomon@google.com return GenBaseGradientKey(drawEffect); 480d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com } 481d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 482d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comprivate: 483d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4840707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.com typedef GrGLGradientEffect INHERITED; 485d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 486d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com}; 487d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 48898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 48998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 49098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comclass GrRadialGradient : public GrGradientEffect { 49198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.compublic: 4920ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com static GrEffectRef* Create(GrContext* ctx, 4930ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkRadialGradient& shader, 4940ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkMatrix& matrix, 4950ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com SkShader::TileMode tm) { 4966340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com AutoEffectUnref effect(SkNEW_ARGS(GrRadialGradient, (ctx, shader, matrix, tm))); 497a1ebbe447d5eab098111eb83580e55f2f5f6facabsalomon@google.com return CreateEffectRef(effect); 49898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 49998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com virtual ~GrRadialGradient() { } 50198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com static const char* Name() { return "Radial Gradient"; } 503396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 504396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com return GrTBackendEffectFactory<GrRadialGradient>::getInstance(); 50598e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 50698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 507422e81aeb1f4078367c85efe591c7df8c33874ecbsalomon@google.com typedef GrGLRadialGradient GLEffect; 50898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comprivate: 5100ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrRadialGradient(GrContext* ctx, 5110ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkRadialGradient& shader, 5120ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkMatrix& matrix, 5130ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com SkShader::TileMode tm) 5140ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com : INHERITED(ctx, shader, matrix, tm) { 5150ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 5160ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 517f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com GR_DECLARE_EFFECT_TEST; 51898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 51998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com typedef GrGradientEffect INHERITED; 52098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com}; 52198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 52298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 52398e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 524f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrRadialGradient); 525d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 526e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgGrEffectRef* GrRadialGradient::TestCreate(SkRandom* random, 5270ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrContext* context, 528c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com const GrDrawTargetCaps&, 5290ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrTexture**) { 530d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkPoint center = {random->nextUScalar1(), random->nextUScalar1()}; 531d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar radius = random->nextUScalar1(); 532d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 533d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkColor colors[kMaxRandomGradientColors]; 534d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar stopsArray[kMaxRandomGradientColors]; 535d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar* stops = stopsArray; 536d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkShader::TileMode tm; 537d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com int colorCount = RandomGradientParams(random, colors, &stops, &tm); 538d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center, radius, 539d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com colors, stops, colorCount, 540d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com tm)); 541e197cbf9a3e66bab926bc5e51962752dad5221a0bsalomon@google.com SkPaint paint; 5429de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrColor grColor; 5439de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrEffectRef* effect; 5449de5b514d38c5b36066bcdc14fba2f7e5196d372dandov shader->asNewEffect(context, paint, NULL, &grColor, &effect); 5459de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return effect; 546d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com} 547d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 548d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com///////////////////////////////////////////////////////////////////// 549d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 550f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.comvoid GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder, 551c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com const GrDrawEffect&, 552d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com EffectKey key, 553f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 554f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 55577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 556f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray& samplers) { 55782d1223aece4703bc9f3a3612cbabaa8c2f2809bbsalomon@google.com this->emitUniforms(builder, key); 558d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com SkString t("length("); 55977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com t.append(builder->ensureFSCoords2D(coords, 0)); 560d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com t.append(")"); 56182d1223aece4703bc9f3a3612cbabaa8c2f2809bbsalomon@google.com this->emitColor(builder, t.c_str(), key, outputColor, inputColor, samplers); 562d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 563d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 564d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 565d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 5669de5b514d38c5b36066bcdc14fba2f7e5196d372dandovbool SkRadialGradient::asNewEffect(GrContext* context, const SkPaint& paint, 5679de5b514d38c5b36066bcdc14fba2f7e5196d372dandov const SkMatrix* localMatrix, GrColor* grColor, 5689de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrEffectRef** grEffect) const { 56900835cc55046e66b5a33633ec045bc9aa0015ebdbsalomon@google.com SkASSERT(NULL != context); 5709de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 571dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com SkMatrix matrix; 572f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com if (!this->getLocalMatrix().invert(&matrix)) { 5739de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 574dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com } 57596fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (localMatrix) { 57696fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org SkMatrix inv; 57796fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (!localMatrix->invert(&inv)) { 5789de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 57996fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 58096fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org matrix.postConcat(inv); 58196fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 582f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com matrix.postConcat(fPtsToUnit); 5839de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 5849de5b514d38c5b36066bcdc14fba2f7e5196d372dandov *grColor = SkColor2GrColorJustAlpha(paint.getColor()); 5859de5b514d38c5b36066bcdc14fba2f7e5196d372dandov *grEffect = GrRadialGradient::Create(context, *this, matrix, fTileMode); 5869de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 5879de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 588d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 589d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 590cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 591cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 5929de5b514d38c5b36066bcdc14fba2f7e5196d372dandovbool SkRadialGradient::asNewEffect(GrContext* context, const SkPaint& paint, 5939de5b514d38c5b36066bcdc14fba2f7e5196d372dandov const SkMatrix* localMatrix, GrColor* grColor, 5949de5b514d38c5b36066bcdc14fba2f7e5196d372dandov GrEffectRef** grEffect) const { 595cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 5969de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 597cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com} 598cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 599cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 60076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 6010f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 60276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkRadialGradient::toString(SkString* str) const { 60376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkRadialGradient: ("); 604ff21c2e0ae23da0f4742b47d4d37969a2a18bd99skia.committer@gmail.com 60576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("center: ("); 60676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter.fX); 60776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(", "); 60876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter.fY); 60976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(") radius: "); 61076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fRadius); 61176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(" "); 61276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 61376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 61476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 61576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 61676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 61776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 618