Home | History | Annotate | Download | only in gradients
      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 "SkLinearGradient.h"
      9 
     10 #include "Sk4fLinearGradient.h"
     11 #include "SkColorSpaceXformer.h"
     12 #include "SkReadBuffer.h"
     13 #include "SkWriteBuffer.h"
     14 
     15 static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) {
     16     SkVector    vec = pts[1] - pts[0];
     17     SkScalar    mag = vec.length();
     18     SkScalar    inv = mag ? SkScalarInvert(mag) : 0;
     19 
     20     vec.scale(inv);
     21     SkMatrix matrix;
     22     matrix.setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
     23     matrix.postTranslate(-pts[0].fX, -pts[0].fY);
     24     matrix.postScale(inv, inv);
     25     return matrix;
     26 }
     27 
     28 ///////////////////////////////////////////////////////////////////////////////
     29 
     30 SkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc)
     31     : SkGradientShaderBase(desc, pts_to_unit_matrix(pts))
     32     , fStart(pts[0])
     33     , fEnd(pts[1]) {
     34 }
     35 
     36 sk_sp<SkFlattenable> SkLinearGradient::CreateProc(SkReadBuffer& buffer) {
     37     DescriptorScope desc;
     38     if (!desc.unflatten(buffer)) {
     39         return nullptr;
     40     }
     41     SkPoint pts[2];
     42     pts[0] = buffer.readPoint();
     43     pts[1] = buffer.readPoint();
     44     return SkGradientShader::MakeLinear(pts, desc.fColors, std::move(desc.fColorSpace), desc.fPos,
     45                                         desc.fCount, desc.fTileMode, desc.fGradFlags,
     46                                         desc.fLocalMatrix);
     47 }
     48 
     49 void SkLinearGradient::flatten(SkWriteBuffer& buffer) const {
     50     this->INHERITED::flatten(buffer);
     51     buffer.writePoint(fStart);
     52     buffer.writePoint(fEnd);
     53 }
     54 
     55 #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
     56 SkShaderBase::Context* SkLinearGradient::onMakeContext(
     57     const ContextRec& rec, SkArenaAlloc* alloc) const
     58 {
     59     return fTileMode != kDecal_TileMode
     60         ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec)
     61         : nullptr;
     62 }
     63 
     64 SkShaderBase::Context* SkLinearGradient::onMakeBurstPipelineContext(
     65     const ContextRec& rec, SkArenaAlloc* alloc) const {
     66 
     67     if (fTileMode == SkShader::kDecal_TileMode) {
     68         // we only support decal w/ stages
     69         return nullptr;
     70     }
     71     // Raster pipeline has a 2-stop specialization faster than our burst.
     72     return fColorCount > 2 ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec)
     73                            : nullptr;
     74 }
     75 #endif
     76 
     77 void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
     78                                             SkRasterPipeline*) const {
     79     // No extra stage needed for linear gradients.
     80 }
     81 
     82 sk_sp<SkShader> SkLinearGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
     83     const AutoXformColors xformedColors(*this, xformer);
     84     SkPoint pts[2] = { fStart, fEnd };
     85     return SkGradientShader::MakeLinear(pts, xformedColors.fColors.get(), fOrigPos, fColorCount,
     86                                         fTileMode, fGradFlags, &this->getLocalMatrix());
     87 }
     88 
     89 SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
     90     if (info) {
     91         commonAsAGradient(info);
     92         info->fPoint[0] = fStart;
     93         info->fPoint[1] = fEnd;
     94     }
     95     return kLinear_GradientType;
     96 }
     97 
     98 /////////////////////////////////////////////////////////////////////
     99 
    100 #if SK_SUPPORT_GPU
    101 
    102 #include "gradients/GrGradientShader.h"
    103 
    104 std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
    105         const GrFPArgs& args) const {
    106     return GrGradientShader::MakeLinear(*this, args);
    107 }
    108 
    109 #endif
    110