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