LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/effects/gradients - SkSweepGradient.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 131 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "SkSweepGradient.h"
       9             : 
      10           0 : static SkMatrix translate(SkScalar dx, SkScalar dy) {
      11             :     SkMatrix matrix;
      12           0 :     matrix.setTranslate(dx, dy);
      13           0 :     return matrix;
      14             : }
      15             : 
      16           0 : SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor& desc)
      17           0 :     : SkGradientShaderBase(desc, translate(-cx, -cy))
      18           0 :     , fCenter(SkPoint::Make(cx, cy))
      19             : {
      20             :     // overwrite the tilemode to a canonical value (since sweep ignores it)
      21           0 :     fTileMode = SkShader::kClamp_TileMode;
      22           0 : }
      23             : 
      24           0 : SkShader::GradientType SkSweepGradient::asAGradient(GradientInfo* info) const {
      25           0 :     if (info) {
      26           0 :         commonAsAGradient(info);
      27           0 :         info->fPoint[0] = fCenter;
      28             :     }
      29           0 :     return kSweep_GradientType;
      30             : }
      31             : 
      32           0 : sk_sp<SkFlattenable> SkSweepGradient::CreateProc(SkReadBuffer& buffer) {
      33           0 :     DescriptorScope desc;
      34           0 :     if (!desc.unflatten(buffer)) {
      35           0 :         return nullptr;
      36             :     }
      37           0 :     const SkPoint center = buffer.readPoint();
      38           0 :     return SkGradientShader::MakeSweep(center.x(), center.y(), desc.fColors,
      39           0 :                                        std::move(desc.fColorSpace), desc.fPos, desc.fCount,
      40           0 :                                        desc.fGradFlags, desc.fLocalMatrix);
      41             : }
      42             : 
      43           0 : void SkSweepGradient::flatten(SkWriteBuffer& buffer) const {
      44           0 :     this->INHERITED::flatten(buffer);
      45           0 :     buffer.writePoint(fCenter);
      46           0 : }
      47             : 
      48           0 : SkShader::Context* SkSweepGradient::onMakeContext(
      49             :     const ContextRec& rec, SkArenaAlloc* alloc) const
      50             : {
      51           0 :     return CheckedMakeContext<SweepGradientContext>(alloc, *this, rec);
      52             : }
      53             : 
      54           0 : SkSweepGradient::SweepGradientContext::SweepGradientContext(
      55           0 :         const SkSweepGradient& shader, const ContextRec& rec)
      56           0 :     : INHERITED(shader, rec) {}
      57             : 
      58             : //  returns angle in a circle [0..2PI) -> [0..255]
      59           0 : static unsigned SkATan2_255(float y, float x) {
      60             :     //    static const float g255Over2PI = 255 / (2 * SK_ScalarPI);
      61             :     static const float g255Over2PI = 40.584510488433314f;
      62             : 
      63           0 :     float result = sk_float_atan2(y, x);
      64           0 :     if (!SkScalarIsFinite(result)) {
      65           0 :         return 0;
      66             :     }
      67           0 :     if (result < 0) {
      68           0 :         result += 2 * SK_ScalarPI;
      69             :     }
      70           0 :     SkASSERT(result >= 0);
      71             :     // since our value is always >= 0, we can cast to int, which is faster than
      72             :     // calling floorf()
      73           0 :     int ir = (int)(result * g255Over2PI);
      74           0 :     SkASSERT(ir >= 0 && ir <= 255);
      75           0 :     return ir;
      76             : }
      77             : 
      78           0 : void SkSweepGradient::SweepGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
      79             :                                                       int count) {
      80           0 :     SkMatrix::MapXYProc proc = fDstToIndexProc;
      81           0 :     const SkMatrix&     matrix = fDstToIndex;
      82           0 :     const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
      83           0 :     int                 toggle = init_dither_toggle(x, y);
      84             :     SkPoint             srcPt;
      85             : 
      86           0 :     if (fDstToIndexClass != kPerspective_MatrixClass) {
      87           0 :         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
      88           0 :                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
      89           0 :         SkScalar dx, fx = srcPt.fX;
      90           0 :         SkScalar dy, fy = srcPt.fY;
      91             : 
      92           0 :         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
      93           0 :             const auto step = matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf);
      94           0 :             dx = step.fX;
      95           0 :             dy = step.fY;
      96             :         } else {
      97           0 :             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
      98           0 :             dx = matrix.getScaleX();
      99           0 :             dy = matrix.getSkewY();
     100             :         }
     101             : 
     102           0 :         for (; count > 0; --count) {
     103           0 :             *dstC++ = cache[toggle + SkATan2_255(fy, fx)];
     104           0 :             fx += dx;
     105           0 :             fy += dy;
     106           0 :             toggle = next_dither_toggle(toggle);
     107             :         }
     108             :     } else {  // perspective case
     109           0 :         for (int stop = x + count; x < stop; x++) {
     110           0 :             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
     111           0 :                          SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
     112           0 :             *dstC++ = cache[toggle + SkATan2_255(srcPt.fY, srcPt.fX)];
     113           0 :             toggle = next_dither_toggle(toggle);
     114             :         }
     115             :     }
     116           0 : }
     117             : 
     118             : /////////////////////////////////////////////////////////////////////
     119             : 
     120             : #if SK_SUPPORT_GPU
     121             : 
     122             : #include "SkGr.h"
     123             : #include "GrShaderCaps.h"
     124             : #include "gl/GrGLContext.h"
     125             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
     126             : 
     127             : class GrSweepGradient : public GrGradientEffect {
     128             : public:
     129             :     class GLSLSweepProcessor;
     130             : 
     131           0 :     static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args) {
     132           0 :         return sk_sp<GrFragmentProcessor>(new GrSweepGradient(args));
     133             :     }
     134           0 :     ~GrSweepGradient() override {}
     135             : 
     136           0 :     const char* name() const override { return "Sweep Gradient"; }
     137             : 
     138             : private:
     139           0 :     GrSweepGradient(const CreateArgs& args) : INHERITED(args, args.fShader->colorsAreOpaque()) {
     140           0 :         this->initClassID<GrSweepGradient>();
     141           0 :     }
     142             : 
     143             :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     144             : 
     145             :     virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
     146             :                                        GrProcessorKeyBuilder* b) const override;
     147             : 
     148             :     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     149             : 
     150             :     typedef GrGradientEffect INHERITED;
     151             : };
     152             : 
     153             : /////////////////////////////////////////////////////////////////////
     154             : 
     155             : class GrSweepGradient::GLSLSweepProcessor : public GrGradientEffect::GLSLProcessor {
     156             : public:
     157           0 :     GLSLSweepProcessor(const GrProcessor&) {}
     158           0 :     ~GLSLSweepProcessor() override {}
     159             : 
     160             :     virtual void emitCode(EmitArgs&) override;
     161             : 
     162           0 :     static void GenKey(const GrProcessor& processor, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
     163           0 :         b->add32(GenBaseGradientKey(processor));
     164           0 :     }
     165             : 
     166             : private:
     167             :     typedef GrGradientEffect::GLSLProcessor INHERITED;
     168             : 
     169             : };
     170             : 
     171             : /////////////////////////////////////////////////////////////////////
     172             : 
     173           0 : GrGLSLFragmentProcessor* GrSweepGradient::onCreateGLSLInstance() const {
     174           0 :     return new GrSweepGradient::GLSLSweepProcessor(*this);
     175             : }
     176             : 
     177           0 : void GrSweepGradient::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     178             :                                             GrProcessorKeyBuilder* b) const {
     179           0 :     GrSweepGradient::GLSLSweepProcessor::GenKey(*this, caps, b);
     180           0 : }
     181             : 
     182             : 
     183             : /////////////////////////////////////////////////////////////////////
     184             : 
     185             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSweepGradient);
     186             : 
     187             : #if GR_TEST_UTILS
     188           0 : sk_sp<GrFragmentProcessor> GrSweepGradient::TestCreate(GrProcessorTestData* d) {
     189           0 :     SkPoint center = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
     190             : 
     191           0 :     RandomGradientParams params(d->fRandom);
     192           0 :     auto shader = params.fUseColors4f ?
     193             :         SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors4f, params.fColorSpace,
     194           0 :                                     params.fStops, params.fColorCount) :
     195             :         SkGradientShader::MakeSweep(center.fX, center.fY,  params.fColors,
     196           0 :                                     params.fStops, params.fColorCount);
     197           0 :     GrTest::TestAsFPArgs asFPArgs(d);
     198           0 :     sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
     199           0 :     GrAlwaysAssert(fp);
     200           0 :     return fp;
     201             : }
     202             : #endif
     203             : 
     204             : /////////////////////////////////////////////////////////////////////
     205             : 
     206           0 : void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
     207           0 :     const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
     208           0 :     this->emitUniforms(args.fUniformHandler, ge);
     209           0 :     SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
     210           0 :     SkString t;
     211             :     // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
     212           0 :     if (args.fShaderCaps->atan2ImplementedAsAtanYOverX()) {
     213             :         // On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is
     214             :         // atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in
     215             :         // (sqrt(x^2 + y^2) + x) as the second parameter to atan2 in these cases. We let the device
     216             :         // handle the undefined behavior of the second paramenter being 0 instead of doing the
     217             :         // divide ourselves and using atan instead.
     218           0 :         t.printf("(2.0 * atan(- %s.y, length(%s) - %s.x) * 0.1591549430918 + 0.5)",
     219           0 :                  coords2D.c_str(), coords2D.c_str(), coords2D.c_str());
     220             :     } else {
     221           0 :         t.printf("(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5)",
     222           0 :                  coords2D.c_str(), coords2D.c_str());
     223             :     }
     224           0 :     this->emitColor(args.fFragBuilder,
     225             :                     args.fUniformHandler,
     226             :                     args.fShaderCaps,
     227             :                     ge, t.c_str(),
     228             :                     args.fOutputColor,
     229             :                     args.fInputColor,
     230           0 :                     args.fTexSamplers);
     231           0 : }
     232             : 
     233             : /////////////////////////////////////////////////////////////////////
     234             : 
     235           0 : sk_sp<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(const AsFPArgs& args) const {
     236             : 
     237             :     SkMatrix matrix;
     238           0 :     if (!this->getLocalMatrix().invert(&matrix)) {
     239           0 :         return nullptr;
     240             :     }
     241           0 :     if (args.fLocalMatrix) {
     242             :         SkMatrix inv;
     243           0 :         if (!args.fLocalMatrix->invert(&inv)) {
     244           0 :             return nullptr;
     245             :         }
     246           0 :         matrix.postConcat(inv);
     247             :     }
     248           0 :     matrix.postConcat(fPtsToUnit);
     249             : 
     250           0 :     sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
     251           0 :                                                                        args.fDstColorSpace);
     252             :     sk_sp<GrFragmentProcessor> inner(GrSweepGradient::Make(
     253           0 :         GrGradientEffect::CreateArgs(args.fContext, this, &matrix, SkShader::kClamp_TileMode,
     254           0 :                                      std::move(colorSpaceXform), SkToBool(args.fDstColorSpace))));
     255           0 :     return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
     256             : }
     257             : 
     258             : #endif
     259             : 
     260             : #ifndef SK_IGNORE_TO_STRING
     261           0 : void SkSweepGradient::toString(SkString* str) const {
     262           0 :     str->append("SkSweepGradient: (");
     263             : 
     264           0 :     str->append("center: (");
     265           0 :     str->appendScalar(fCenter.fX);
     266           0 :     str->append(", ");
     267           0 :     str->appendScalar(fCenter.fY);
     268           0 :     str->append(") ");
     269             : 
     270           0 :     this->INHERITED::toString(str);
     271             : 
     272           0 :     str->append(")");
     273           0 : }
     274             : #endif

Generated by: LCOV version 1.13