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 148addf2edf3da20f053daa3897cfe2c52d7369a7b1reedSkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor& desc) 149addf2edf3da20f053daa3897cfe2c52d7369a7b1reed : SkGradientShaderBase(desc) 150addf2edf3da20f053daa3897cfe2c52d7369a7b1reed , fCenter(center) 151addf2edf3da20f053daa3897cfe2c52d7369a7b1reed , fRadius(radius) 152589708bf7c706348b763e8277004cb160b202bdbrileya@google.com{ 153589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // make sure our table is insync with our current #define for kSQRT_TABLE_SIZE 154589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE); 155589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 156589708bf7c706348b763e8277004cb160b202bdbrileya@google.com rad_to_unit_matrix(center, radius, &fPtsToUnit); 157589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 158589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 15987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkRadialGradient::contextSize() const { 16087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(RadialGradientContext); 16187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 16287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 163ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkRadialGradient::onCreateContext(const ContextRec& rec, void* storage) const { 164e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, rec)); 16587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 16687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 16787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkRadialGradient::RadialGradientContext::RadialGradientContext( 168e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkRadialGradient& shader, const ContextRec& rec) 169e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) {} 17087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 17187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkRadialGradient::RadialGradientContext::shadeSpan16(int x, int y, uint16_t* dstCParam, 17287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int count) { 173589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 174589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 17587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader); 17687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 177589708bf7c706348b763e8277004cb160b202bdbrileya@google.com uint16_t* SK_RESTRICT dstC = dstCParam; 178589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 179589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 180589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 18187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = radialGradient.fTileProc; 18287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const uint16_t* SK_RESTRICT cache = fCache->getCache16(); 18355853db3cce9539746fe202519a534c85ecdf62creed@google.com int toggle = init_dither_toggle16(x, y); 184589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 185589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 186589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 187589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 188589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 189589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdx = fDstToIndex.getScaleX(); 190589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdy = fDstToIndex.getSkewY(); 191589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 192589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 193589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed storage[2]; 194589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), 195589708bf7c706348b763e8277004cb160b202bdbrileya@google.com &storage[0], &storage[1]); 196589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdx = SkFixedToScalar(storage[0]); 197589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdy = SkFixedToScalar(storage[1]); 198589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 199589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 200589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 201589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 202589708bf7c706348b763e8277004cb160b202bdbrileya@google.com RadialShade16Proc shadeProc = shadeSpan16_radial_repeat; 20387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { 204589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_radial_clamp; 20587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { 206589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan16_radial_mirror; 207589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 20887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); 209589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 210589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, 211589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache, toggle, count); 212589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { // perspective case 213589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 214589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 215589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 216589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 217589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(SkScalarToFixed(srcPt.length())); 218589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 219589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 220589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int index = fi >> (16 - kCache16Bits); 221589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + index]; 22255853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle16(toggle); 223589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 224589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 225589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 226589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 227589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 228589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 229fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comSkShader::BitmapType SkRadialGradient::asABitmap(SkBitmap* bitmap, 230589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix* matrix, SkShader::TileMode* xy) const { 231589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (bitmap) { 2321c6d64b78b24083ee9fd7411dac8a4a7e2d03a3crileya@google.com this->getGradientTableBitmap(bitmap); 233589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 234589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (matrix) { 2353c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com matrix->setScale(SkIntToScalar(kCache32Count), 2363c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com SkIntToScalar(kCache32Count)); 237589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->preConcat(fPtsToUnit); 238589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 239589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (xy) { 240589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[0] = fTileMode; 241589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[1] = kClamp_TileMode; 242589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 243589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kRadial_BitmapType; 244589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 245589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 246589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::GradientType SkRadialGradient::asAGradient(GradientInfo* info) const { 247589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info) { 248589708bf7c706348b763e8277004cb160b202bdbrileya@google.com commonAsAGradient(info); 249589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fPoint[0] = fCenter; 250589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fRadius[0] = fRadius; 251589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 252589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kRadial_GradientType; 253589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 254589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 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} 2619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 2629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkRadialGradient::CreateProc(SkReadBuffer& buffer) { 2649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed DescriptorScope desc; 2659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!desc.unflatten(buffer)) { 2669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 2679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 2689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkPoint center = buffer.readPoint(); 2699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar radius = buffer.readScalar(); 2709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkGradientShader::CreateRadial(center, radius, desc.fColors, desc.fPos, desc.fCount, 2719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed desc.fTileMode, desc.fGradFlags, desc.fLocalMatrix); 2729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 273589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2748b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkRadialGradient::flatten(SkWriteBuffer& buffer) const { 275589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->INHERITED::flatten(buffer); 276589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writePoint(fCenter); 277589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeScalar(fRadius); 278589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 279589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 280589708bf7c706348b763e8277004cb160b202bdbrileya@google.comnamespace { 281589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 282589708bf7c706348b763e8277004cb160b202bdbrileya@google.cominline bool radial_completely_pinned(int fx, int dx, int fy, int dy) { 283589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // fast, overly-conservative test: checks unit square instead 284589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // of unit circle 285589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bool xClamped = (fx >= SK_FixedHalf && dx >= 0) || 286589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (fx <= -SK_FixedHalf && dx <= 0); 287589708bf7c706348b763e8277004cb160b202bdbrileya@google.com bool yClamped = (fy >= SK_FixedHalf && dy >= 0) || 288589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (fy <= -SK_FixedHalf && dy <= 0); 289589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 290589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return xClamped || yClamped; 291589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 292589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 293589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Return true if (fx * fy) is always inside the unit circle 294589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// SkPin32 is expensive, but so are all the SkFixedMul in this test, 295589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// so it shouldn't be run if count is small. 296589708bf7c706348b763e8277004cb160b202bdbrileya@google.cominline bool no_need_for_radial_pin(int fx, int dx, 297589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int fy, int dy, int count) { 298589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 299589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) { 300589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 301589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 302589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fx*fx + fy*fy > 0x7FFF*0x7FFF) { 303589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 304589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 305589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += (count - 1) * dx; 306589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += (count - 1) * dy; 307589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) { 308589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return false; 309589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 310589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return fx*fx + fy*fy <= 0x7FFF*0x7FFF; 311589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 312589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 313589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#define UNPINNED_RADIAL_STEP \ 314589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = (fx * fx + fy * fy) >> (14 + 16 - kSQRT_TABLE_BITS); \ 315589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + \ 316589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (sqrt_table[fi] >> SkGradientShaderBase::kSqrt32Shift)]; \ 31755853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); \ 318589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; \ 319589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 320589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 321589708bf7c706348b763e8277004cb160b202bdbrileya@google.comtypedef void (* RadialShadeProc)(SkScalar sfx, SkScalar sdx, 322589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sfy, SkScalar sdy, 323589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* dstC, const SkPMColor* cache, 324589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count, int toggle); 325589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 326589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// On Linux, this is faster with SkPMColor[] params than SkPMColor* SK_RESTRICT 327589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx, 328589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sfy, SkScalar sdy, 329589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 330589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count, int toggle) { 331589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Floating point seems to be slower than fixed point, 332589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // even when we have float hardware. 333589708bf7c706348b763e8277004cb160b202bdbrileya@google.com const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table; 334589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fx = SkScalarToFixed(sfx) >> 1; 335589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dx = SkScalarToFixed(sdx) >> 1; 336589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fy = SkScalarToFixed(sfy) >> 1; 337589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed dy = SkScalarToFixed(sdy) >> 1; 338589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) { 3393c2102c2d2cdad328a0d87329e1a973f12775836reed@google.com unsigned fi = SkGradientShaderBase::kCache32Count - 1; 340589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_memset32_dither(dstC, 341589708bf7c706348b763e8277004cb160b202bdbrileya@google.com cache[toggle + fi], 34255853db3cce9539746fe202519a534c85ecdf62creed@google.com cache[next_dither_toggle(toggle) + fi], 343589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count); 344589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else if ((count > 4) && 345589708bf7c706348b763e8277004cb160b202bdbrileya@google.com no_need_for_radial_pin(fx, dx, fy, dy, count)) { 346589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi; 347589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // 4x unroll appears to be no faster than 2x unroll on Linux 348589708bf7c706348b763e8277004cb160b202bdbrileya@google.com while (count > 1) { 349589708bf7c706348b763e8277004cb160b202bdbrileya@google.com UNPINNED_RADIAL_STEP; 350589708bf7c706348b763e8277004cb160b202bdbrileya@google.com UNPINNED_RADIAL_STEP; 351589708bf7c706348b763e8277004cb160b202bdbrileya@google.com count -= 2; 352589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 353589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (count) { 354589708bf7c706348b763e8277004cb160b202bdbrileya@google.com UNPINNED_RADIAL_STEP; 355589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 35660040292be58ac553298209fb2e0684a4cb17dccreed@google.com } else { 357589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Specializing for dy == 0 gains us 25% on Skia benchmarks 358589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (dy == 0) { 359589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned yy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); 360589708bf7c706348b763e8277004cb160b202bdbrileya@google.com yy *= yy; 361589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 362589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); 363589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = (xx * xx + yy) >> (14 + 16 - kSQRT_TABLE_BITS); 364589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); 365589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (sqrt_table[fi] >> 366589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkGradientShaderBase::kSqrt32Shift)]; 36755853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 368589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 369589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 370589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 371589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 372589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1); 373589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1); 374589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS); 375589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS)); 376589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (sqrt_table[fi] >> 377589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkGradientShaderBase::kSqrt32Shift)]; 37855853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 379589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 380589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 381589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 382589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 383589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 384589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 385589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 386589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// Unrolling this loop doesn't seem to help (when float); we're stalling to 387589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// get the results of the sqrt (?), and don't have enough extra registers to 388589708bf7c706348b763e8277004cb160b202bdbrileya@google.com// have many in flight. 38934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgtemplate <SkFixed (*TileProc)(SkFixed)> 39034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 39134150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 39234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int count, int toggle) { 393589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 39434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy)); 39534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org const unsigned fi = TileProc(dist); 396589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 397589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache32Shift)]; 39855853db3cce9539746fe202519a534c85ecdf62creed@google.com toggle = next_dither_toggle(toggle); 399589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 400589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 401589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 402589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 40334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 40434150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 40534150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 40634150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int count, int toggle) { 40734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org shadeSpan_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle); 40834150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} 40934150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 41034150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.orgvoid shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy, 41134150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 41234150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org int count, int toggle) { 41334150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org shadeSpan_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle); 414589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 415589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 41634150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org} // namespace 41734150b451da7d3c70a2d34e67b0285cb36932d45commit-bot@chromium.org 41887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y, 41987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor* SK_RESTRICT dstC, int count) { 420589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 421589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 42287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader); 42387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 424589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 425589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 42687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = radialGradient.fTileProc; 42787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); 42855853db3cce9539746fe202519a534c85ecdf62creed@google.com int toggle = init_dither_toggle(x, y); 429589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 430589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 431589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 432589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 433589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdx = fDstToIndex.getScaleX(); 434589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sdy = fDstToIndex.getSkewY(); 435589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 436589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 437589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed storage[2]; 438589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), 439589708bf7c706348b763e8277004cb160b202bdbrileya@google.com &storage[0], &storage[1]); 440589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdx = SkFixedToScalar(storage[0]); 441589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sdy = SkFixedToScalar(storage[1]); 442589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 443589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 444589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 445589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 446589708bf7c706348b763e8277004cb160b202bdbrileya@google.com RadialShadeProc shadeProc = shadeSpan_radial_repeat; 44787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (SkShader::kClamp_TileMode == radialGradient.fTileMode) { 448589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_radial_clamp; 44987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) { 450589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_radial_mirror; 451589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 45287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode); 453589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 454589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle); 455589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { // perspective case 456589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 457589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 458589708bf7c706348b763e8277004cb160b202bdbrileya@google.com do { 459589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 460589708bf7c706348b763e8277004cb160b202bdbrileya@google.com unsigned fi = proc(SkScalarToFixed(srcPt.length())); 461589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fi <= 0xFFFF); 462589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[fi >> SkGradientShaderBase::kCache32Shift]; 463589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 464589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } while (--count != 0); 465589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 466589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 467589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 468d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 469d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 470cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 471cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 472b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 47330ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 4749de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#include "SkGr.h" 4752eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com 4760707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.comclass GrGLRadialGradient : public GrGLGradientEffect { 477d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.compublic: 478d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 479b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGLRadialGradient(const GrBackendProcessorFactory& factory, 480b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor&) : INHERITED (factory) { } 481d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com virtual ~GrGLRadialGradient() { } 482d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 48330ba436f04e61d4505fb854d5fc56079636e0788joshualitt virtual void emitCode(GrGLProgramBuilder*, 484b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 485b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey&, 486f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 487f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 48877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 489f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 490d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 491b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static void GenKey(const GrProcessor& processor, const GrGLCaps&, GrProcessorKeyBuilder* b) { 492b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt b->add32(GenBaseGradientKey(processor)); 493d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com } 494d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 495d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comprivate: 496d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4970707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.com typedef GrGLGradientEffect INHERITED; 498d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 499d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com}; 500d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 50198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 50298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50398e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comclass GrRadialGradient : public GrGradientEffect { 50498e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.compublic: 505b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(GrContext* ctx, 506b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkRadialGradient& shader, 507b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix& matrix, 508b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkShader::TileMode tm) { 50955fad7af61c21d502acb9891d631e8aa29e3628cbsalomon return SkNEW_ARGS(GrRadialGradient, (ctx, shader, matrix, tm)); 51098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 51198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 51298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com virtual ~GrRadialGradient() { } 51398e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 51498e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com static const char* Name() { return "Radial Gradient"; } 515b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE { 516b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendFragmentProcessorFactory<GrRadialGradient>::getInstance(); 51798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 51898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 519b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLRadialGradient GLProcessor; 52098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 52198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comprivate: 5220ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrRadialGradient(GrContext* ctx, 5230ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkRadialGradient& shader, 5240ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkMatrix& matrix, 5250ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com SkShader::TileMode tm) 5260ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com : INHERITED(ctx, shader, matrix, tm) { 5270ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 5280ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 529b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 53098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 53198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com typedef GrGradientEffect INHERITED; 53298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com}; 53398e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 53498e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 53598e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 536b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRadialGradient); 537d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 538b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrRadialGradient::TestCreate(SkRandom* random, 539b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext* context, 540b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 541b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture**) { 542d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkPoint center = {random->nextUScalar1(), random->nextUScalar1()}; 543d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar radius = random->nextUScalar1(); 544d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 545d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkColor colors[kMaxRandomGradientColors]; 546d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar stopsArray[kMaxRandomGradientColors]; 547d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar* stops = stopsArray; 548d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkShader::TileMode tm; 549d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com int colorCount = RandomGradientParams(random, colors, &stops, &tm); 550d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center, radius, 551d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com colors, stops, colorCount, 552d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com tm)); 553e197cbf9a3e66bab926bc5e51962752dad5221a0bsalomon@google.com SkPaint paint; 55483d081ae1d731b5039e99823620f5e287542ee39bsalomon GrColor paintColor; 555b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* fp; 556b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkAssertResult(shader->asFragmentProcessor(context, paint, NULL, &paintColor, &fp)); 557b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return fp; 558d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com} 559d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 560d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com///////////////////////////////////////////////////////////////////// 561d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 56230ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLRadialGradient::emitCode(GrGLProgramBuilder* builder, 563b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 564b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 565f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 566f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 56777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 568f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray& samplers) { 56963e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon uint32_t baseKey = key.get32(0); 57063e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon this->emitUniforms(builder, baseKey); 571d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com SkString t("length("); 57230ba436f04e61d4505fb854d5fc56079636e0788joshualitt t.append(builder->getFragmentShaderBuilder()->ensureFSCoords2D(coords, 0)); 573d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com t.append(")"); 57463e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon this->emitColor(builder, t.c_str(), baseKey, outputColor, inputColor, samplers); 575d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 576d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 577d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 578d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 579b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkRadialGradient::asFragmentProcessor(GrContext* context, const SkPaint& paint, 580b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix* localMatrix, GrColor* paintColor, 581b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor** fp) const { 58249f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(context); 5839de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 584dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com SkMatrix matrix; 585f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com if (!this->getLocalMatrix().invert(&matrix)) { 5869de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 587dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com } 58896fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (localMatrix) { 58996fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org SkMatrix inv; 59096fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (!localMatrix->invert(&inv)) { 5919de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 59296fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 59396fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org matrix.postConcat(inv); 59496fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 595f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com matrix.postConcat(fPtsToUnit); 5969de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 59783d081ae1d731b5039e99823620f5e287542ee39bsalomon *paintColor = SkColor2GrColorJustAlpha(paint.getColor()); 598b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = GrRadialGradient::Create(context, *this, matrix, fTileMode); 5999de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 6009de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 601d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 602d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 603cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 604cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 605b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkRadialGradient::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, 606b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor**) const { 607cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 6089de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 609cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com} 610cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 611cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 61276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 6130f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 61476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkRadialGradient::toString(SkString* str) const { 61576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkRadialGradient: ("); 616ff21c2e0ae23da0f4742b47d4d37969a2a18bd99skia.committer@gmail.com 61776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("center: ("); 61876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter.fX); 61976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(", "); 62076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter.fY); 62176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(") radius: "); 62276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fRadius); 62376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(" "); 62476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 62576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 62676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 62776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 62876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 62976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 630