1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTwoPointConicalGradient.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRasterPipeline.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkReadBuffer.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkWriteBuffer.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../../jumper/SkJumper.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please see https://skia.org/dev/design/conical for how our shader works. 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTwoPointConicalGradient::FocalData::set(SkScalar r0, SkScalar r1, SkMatrix& matrix) { 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIsSwapped = false; 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFocalX = r0 / (r0 - r1); 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyZero(fFocalX - 1)) { 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // swap r0, r1 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postTranslate(-1, 0); 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postScale(-1, 1); 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::swap(r0, r1); 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFocalX = 0; // because r0 is now 0 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIsSwapped = true; 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Map {focal point, (1, 0)} to {(0, 0), (1, 0)} 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint from[2] = { {fFocalX, 0}, {1, 0} }; 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint to[2] = { {0, 0}, {1, 0} }; 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix focalMatrix; 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!focalMatrix.setPolyToPoly(from, to, 2)) { 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAILF("Mapping focal point failed unexpectedly for focalX = %f.\n", fFocalX); 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We won't be able to draw the gradient; at least make sure that we initialize the 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // memory to prevent security issues. 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot focalMatrix = SkMatrix::MakeScale(1, 1); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postConcat(focalMatrix); 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fR1 = r1 / SkScalarAbs(1 - fFocalX); // focalMatrix has a scale of 1/(1-f) 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The following transformations are just to accelerate the shader computation by saving 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // some arithmatic operations. 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->isFocalOnCircle()) { 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postScale(0.5, 0.5); 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postScale(fR1 / (fR1 * fR1 - 1), 1 / sqrt(SkScalarAbs(fR1 * fR1 - 1))); 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postScale(SkScalarAbs(1 - fFocalX), SkScalarAbs(1 - fFocalX)); // scale |1 - f| 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkTwoPointConicalGradient::Create(const SkPoint& c0, SkScalar r0, 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& c1, SkScalar r1, 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const Descriptor& desc) { 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix gradientMatrix; 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Type gradientType; 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyZero((c0 - c1).length())) { 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Concentric case: we can pretend we're radial (with a tiny twist). 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar scale = 1.0f / SkTMax(r0, r1); 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gradientMatrix = SkMatrix::MakeTrans(-c1.x(), -c1.y()); 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gradientMatrix.postScale(scale, scale); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gradientType = Type::kRadial; 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint centers[2] = { c0 , c1 }; 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint unitvec[2] = { {0, 0}, {1, 0} }; 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!gradientMatrix.setPolyToPoly(centers, unitvec, 2)) { 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Degenerate case. 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gradientType = SkScalarNearlyZero(r1 - r0) ? Type::kStrip : Type::kFocal; 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FocalData focalData; 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (gradientType == Type::kFocal) { 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto dCenter = (c0 - c1).length(); 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot focalData.set(r0 / dCenter, r1 / dCenter, gradientMatrix); // this may change gradientMatrix 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_sp<SkShader>(new SkTwoPointConicalGradient(c0, r0, c1, r1, desc, 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gradientType, gradientMatrix, focalData)); 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTwoPointConicalGradient::SkTwoPointConicalGradient( 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& start, SkScalar startRadius, 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& end, SkScalar endRadius, 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const Descriptor& desc, Type type, const SkMatrix& gradientMatrix, const FocalData& data) 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : SkGradientShaderBase(desc, gradientMatrix) 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fCenter1(start) 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fCenter2(end) 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fRadius1(startRadius) 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fRadius2(endRadius) 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fType(type) 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // this is degenerate, and should be caught by our caller 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2); 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (type == Type::kFocal) { 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFocalData = data; 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkTwoPointConicalGradient::isOpaque() const { 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Because areas outside the cone are left untouched, we cannot treat the 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // shader as opaque even if the gradient itself is opaque. 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO(junov): Compute whether the cone fills the plane crbug.com/222380 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Returns the original non-sorted version of the gradient 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkShader::GradientType SkTwoPointConicalGradient::asAGradient(GradientInfo* info) const { 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (info) { 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot commonAsAGradient(info); 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fPoint[0] = fCenter1; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fPoint[1] = fCenter2; 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fRadius[0] = fRadius1; 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fRadius[1] = fRadius2; 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return kConical_GradientType; 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkFlattenable> SkTwoPointConicalGradient::CreateProc(SkReadBuffer& buffer) { 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DescriptorScope desc; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!desc.unflatten(buffer)) { 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint c1 = buffer.readPoint(); 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint c2 = buffer.readPoint(); 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar r1 = buffer.readScalar(); 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar r2 = buffer.readScalar(); 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (buffer.isVersionLT(SkReadBuffer::k2PtConicalNoFlip_Version) && buffer.readBool()) { 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // legacy flipped gradient 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(c1, c2); 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(r1, r2); 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor4f* colors = desc.mutableColors(); 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar* pos = desc.mutablePos(); 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int last = desc.fCount - 1; 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int half = desc.fCount >> 1; 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < half; ++i) { 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(colors[i], colors[last - i]); 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (pos) { 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar tmp = pos[i]; 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pos[i] = SK_Scalar1 - pos[last - i]; 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pos[last - i] = SK_Scalar1 - tmp; 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (pos) { 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (desc.fCount & 1) { 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pos[half] = SK_Scalar1 - pos[half]; 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkGradientShader::MakeTwoPointConical(c1, r1, c2, r2, desc.fColors, 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::move(desc.fColorSpace), desc.fPos, 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fCount, desc.fTileMode, desc.fGradFlags, 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot desc.fLocalMatrix); 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTwoPointConicalGradient::flatten(SkWriteBuffer& buffer) const { 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->INHERITED::flatten(buffer); 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writePoint(fCenter1); 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writePoint(fCenter2); 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeScalar(fRadius1); 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot buffer.writeScalar(fRadius2); 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_SUPPORT_GPU 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGr.h" 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTwoPointConicalGradient_gpu.h" 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor( 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrFPArgs& args) const { 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(args.fContext); 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return Gr2PtConicalGradientEffect::Make( 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrGradientEffect::CreateArgs(args.fContext, this, args.fLocalMatrix, fTileMode, 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.fDstColorSpaceInfo->colorSpace())); 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkShader> SkTwoPointConicalGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const { 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const AutoXformColors xformedColors(*this, xformer); 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkGradientShader::MakeTwoPointConical(fCenter1, fRadius1, fCenter2, fRadius2, 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot xformedColors.fColors.get(), fOrigPos, fColorCount, 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTileMode, fGradFlags, &this->getLocalMatrix()); 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_IGNORE_TO_STRING 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTwoPointConicalGradient::toString(SkString* str) const { 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append("SkTwoPointConicalGradient: ("); 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append("center1: ("); 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(fCenter1.fX); 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(", "); 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(fCenter1.fY); 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(") radius1: "); 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(fRadius1); 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(" "); 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append("center2: ("); 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(fCenter2.fX); 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(", "); 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(fCenter2.fY); 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(") radius2: "); 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->appendScalar(fRadius2); 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(" "); 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->INHERITED::toString(str); 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot str->append(")"); 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTwoPointConicalGradient::appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* p, 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRasterPipeline* postPipeline) const { 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto dRadius = fRadius2 - fRadius1; 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fType == Type::kRadial) { 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::xy_to_radius); 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Tiny twist: radial computes a t for [0, r2], but we want a t for [r1, r2]. 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto scale = SkTMax(fRadius1, fRadius2) / dRadius; 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto bias = -fRadius1 / dRadius; 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append_matrix(alloc, SkMatrix::Concat(SkMatrix::MakeTrans(bias, 0), 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix::MakeScale(scale, 1))); 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fType == Type::kStrip) { 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto* ctx = alloc->make<SkJumper_2PtConicalCtx>(); 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar scaledR0 = fRadius1 / this->getCenterX1(); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->fP0 = scaledR0 * scaledR0; 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::xy_to_2pt_conical_strip, ctx); 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::mask_2pt_conical_nan, ctx); 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot postPipeline->append(SkRasterPipeline::apply_vector_mask, &ctx->fMask); 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto* ctx = alloc->make<SkJumper_2PtConicalCtx>(); 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->fP0 = 1/fFocalData.fR1; 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ctx->fP1 = fFocalData.fFocalX; 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFocalData.isFocalOnCircle()) { 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::xy_to_2pt_conical_focal_on_circle); 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (fFocalData.isWellBehaved()) { 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::xy_to_2pt_conical_well_behaved, ctx); 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (fFocalData.isSwapped() || 1 - fFocalData.fFocalX < 0) { 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::xy_to_2pt_conical_smaller, ctx); 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::xy_to_2pt_conical_greater, ctx); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fFocalData.isWellBehaved()) { 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::mask_2pt_conical_degenerates, ctx); 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (1 - fFocalData.fFocalX < 0) { 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::negate_x); 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fFocalData.isNativelyFocal()) { 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::alter_2pt_conical_compensate_focal, ctx); 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFocalData.isSwapped()) { 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p->append(SkRasterPipeline::alter_2pt_conical_unswap); 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fFocalData.isWellBehaved()) { 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot postPipeline->append(SkRasterPipeline::apply_vector_mask, &ctx->fMask); 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 276