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 "src/shaders/gradients/SkLinearGradient.h" 9 10#include "src/core/SkReadBuffer.h" 11#include "src/core/SkWriteBuffer.h" 12#include "src/shaders/gradients/Sk4fLinearGradient.h" 13 14static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) { 15 SkVector vec = pts[1] - pts[0]; 16 SkScalar mag = vec.length(); 17 SkScalar inv = mag ? SkScalarInvert(mag) : 0; 18 19 vec.scale(inv); 20 SkMatrix matrix; 21 matrix.setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); 22 matrix.postTranslate(-pts[0].fX, -pts[0].fY); 23 matrix.postScale(inv, inv); 24 return matrix; 25} 26 27/////////////////////////////////////////////////////////////////////////////// 28 29SkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc) 30 : SkGradientShaderBase(desc, pts_to_unit_matrix(pts)) 31 , fStart(pts[0]) 32 , fEnd(pts[1]) { 33} 34 35sk_sp<SkFlattenable> SkLinearGradient::CreateProc(SkReadBuffer& buffer) { 36 DescriptorScope desc; 37 if (!desc.unflatten(buffer)) { 38 return nullptr; 39 } 40 SkPoint pts[2]; 41 pts[0] = buffer.readPoint(); 42 pts[1] = buffer.readPoint(); 43 return SkGradientShader::MakeLinear(pts, desc.fColors, std::move(desc.fColorSpace), desc.fPos, 44 desc.fCount, desc.fTileMode, desc.fGradFlags, 45 desc.fLocalMatrix); 46} 47 48void SkLinearGradient::flatten(SkWriteBuffer& buffer) const { 49 this->INHERITED::flatten(buffer); 50 buffer.writePoint(fStart); 51 buffer.writePoint(fEnd); 52} 53 54#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT 55SkShaderBase::Context* SkLinearGradient::onMakeContext( 56 const ContextRec& rec, SkArenaAlloc* alloc) const 57{ 58 // make sure our colorspaces are compatible with legacy blits 59 if (!rec.isLegacyCompatible(fColorSpace.get())) { 60 return nullptr; 61 } 62 // Can't use legacy blit if we can't represent our colors as SkColors 63 if (!this->colorsCanConvertToSkColor()) { 64 return nullptr; 65 } 66 67 return fTileMode != SkTileMode::kDecal 68 ? CheckedMakeContext<LinearGradient4fContext>(alloc, *this, rec) 69 : nullptr; 70} 71#endif 72 73void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*, 74 SkRasterPipeline*) const { 75 // No extra stage needed for linear gradients. 76} 77 78skvm::F32 SkLinearGradient::transformT(skvm::Builder* p, skvm::Uniforms*, 79 skvm::Coord coord, skvm::I32* mask) const { 80 // We've baked getting t in x into the matrix, so this is pretty trivial. 81 return coord.x; 82} 83 84SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const { 85 if (info) { 86 commonAsAGradient(info); 87 info->fPoint[0] = fStart; 88 info->fPoint[1] = fEnd; 89 } 90 return kLinear_GradientType; 91} 92 93///////////////////////////////////////////////////////////////////// 94 95#if SK_SUPPORT_GPU 96 97#include "src/gpu/gradients/GrGradientShader.h" 98 99std::unique_ptr<GrFragmentProcessor> SkLinearGradient::asFragmentProcessor( 100 const GrFPArgs& args) const { 101 return GrGradientShader::MakeLinear(*this, args); 102} 103 104#endif 105