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     // make sure our colorspaces are compatible with legacy blits
     60     if (!rec.isLegacyCompatible(fColorSpace.get())) {
     61         return nullptr;
     62     }
     63     // Can't use legacy blit if we can't represent our colors as SkColors
     64     if (!this->colorsCanConvertToSkColor()) {
     65         return nullptr;
     66     }
     67 
     68     return fTileMode != kDecal_TileMode
     69         ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec)
     70         : nullptr;
     71 }
     72 
     73 SkShaderBase::Context* SkLinearGradient::onMakeBurstPipelineContext(
     74     const ContextRec& rec, SkArenaAlloc* alloc) const {
     75 
     76     if (fTileMode == SkShader::kDecal_TileMode) {
     77         // we only support decal w/ stages
     78         return nullptr;
     79     }
     80     // Raster pipeline has a 2-stop specialization faster than our burst.
     81     return fColorCount > 2 ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec)
     82                            : nullptr;
     83 }
     84 #endif
     85 
     86 void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
     87                                             SkRasterPipeline*) const {
     88     // No extra stage needed for linear gradients.
     89 }
     90 
     91 sk_sp<SkShader> SkLinearGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
     92     const AutoXformColors xformedColors(*this, xformer);
     93     SkPoint pts[2] = { fStart, fEnd };
     94     return SkGradientShader::MakeLinear(pts, xformedColors.fColors.get(), fOrigPos, fColorCount,
     95                                         fTileMode, fGradFlags, &this->getLocalMatrix());
     96 }
     97 
     98 SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
     99     if (info) {
    100         commonAsAGradient(info);
    101         info->fPoint[0] = fStart;
    102         info->fPoint[1] = fEnd;
    103     }
    104     return kLinear_GradientType;
    105 }
    106 
    107 /////////////////////////////////////////////////////////////////////
    108 
    109 #if SK_SUPPORT_GPU
    110 
    111 #include "gradients/GrGradientShader.h"
    112 
    113 std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor(
    114         const GrFPArgs& args) const {
    115     return GrGradientShader::MakeLinear(*this, args);
    116 }
    117 
    118 #endif
    119