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