Skip to content

Commit

Permalink
Move the MakeLinear() and MakeRadial() methods to Shader.h (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
domchen authored Feb 12, 2022
1 parent 874dff2 commit 230cdb6
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 145 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"common": [
{
"url": "${PAG_GROUP}/vendor_tools.git",
"commit": "1d38eb7b0f428a266a6d6befc07a3d95749c7ef3",
"commit": "9b28c43638b358c05a0a9c26042390e86d1a213d",
"dir": "vendor_tools"
},
{
Expand Down
6 changes: 3 additions & 3 deletions src/rendering/graphics/Shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include "Shape.h"
#include "gpu/Canvas.h"
#include "gpu/GradientShader.h"
#include "gpu/Shader.h"
#include "pag/file.h"

namespace pag {
Expand All @@ -44,11 +44,11 @@ static std::shared_ptr<Shader> MakeGradientShader(const GradientPaint& gradient)
colors.push_back({r, g, b, a});
}
if (gradient.gradientType == GradientFillType::Linear) {
shader = GradientShader::MakeLinear(gradient.startPoint, gradient.endPoint, colors,
shader = Shader::MakeLinearGradient(gradient.startPoint, gradient.endPoint, colors,
gradient.positions);
} else {
auto radius = Point::Distance(gradient.startPoint, gradient.endPoint);
shader = GradientShader::MakeRadial(gradient.startPoint, radius, colors, gradient.positions);
shader = Shader::MakeRadialGradient(gradient.startPoint, radius, colors, gradient.positions);
}
if (!shader) {
shader = Shader::MakeColorShader(gradient.colors.back(), gradient.alphas.back());
Expand Down
59 changes: 0 additions & 59 deletions tgfx/include/gpu/GradientShader.h

This file was deleted.

29 changes: 29 additions & 0 deletions tgfx/include/gpu/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include <memory>
#include "core/Color4f.h"
#include "pag/types.h"

namespace pag {
Expand All @@ -34,6 +35,34 @@ class Shader {
*/
static std::shared_ptr<Shader> MakeColorShader(Color color, Opacity opacity = Opaque);

/**
* Returns a shader that generates a linear gradient between the two specified points.
* @param startPoint The start point for the gradient.
* @param endPoint The end point for the gradient.
* @param colors The array of colors, to be distributed between the two points.
* @param positions May be empty. The relative position of each corresponding color in the colors
* array. If this is empty, the the colors are distributed evenly between the start and end point.
* If this is not empty, the values must begin with 0, end with 1.0, and intermediate values must
* be strictly increasing.
*/
static std::shared_ptr<Shader> MakeLinearGradient(const Point& startPoint, const Point& endPoint,
const std::vector<Color4f>& colors,
const std::vector<float>& positions);

/**
* Returns a shader that generates a radial gradient given the center and radius.
* @param center The center of the circle for this gradient
* @param radius Must be positive. The radius of the circle for this gradient.
* @param colors The array of colors, to be distributed between the center and edge of the circle.
* @param positions May be empty. The relative position of each corresponding color in the colors
* array. If this is empty, the the colors are distributed evenly between the start and end point.
* If this is not empty, the values must begin with 0, end with 1.0, and intermediate values must
* be strictly increasing.
*/
static std::shared_ptr<Shader> MakeRadialGradient(const Point& center, float radius,
const std::vector<Color4f>& colors,
const std::vector<float>& positions);

virtual ~Shader() = default;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "gpu/GradientShader.h"
#include "GradientShader.h"
#include "base/utils/MathExtra.h"
#include "gpu/Caps.h"
#include "gpu/ColorShader.h"
Expand Down Expand Up @@ -110,65 +110,52 @@ static std::unique_ptr<FragmentProcessor> MakeColorizer(Context* context, const
context->gradientCache()->getGradient(colors + offset, positions + offset, count));
}

class GradientShaderBase : public ShaderBase {
public:
GradientShaderBase(const std::vector<Color4f>& colors, const std::vector<float>& positions,
const Matrix& pointsToUnit)
: pointsToUnit(pointsToUnit) {
colorsAreOpaque = true;
for (auto& color : colors) {
if (!color.isOpaque()) {
colorsAreOpaque = false;
break;
}
}
auto dummyFirst = false;
auto dummyLast = false;
if (!positions.empty()) {
dummyFirst = positions[0] != 0;
dummyLast = positions[positions.size() - 1] != 1.0f;
}
// Now copy over the colors, adding the dummies as needed
if (dummyFirst) {
originalColors.push_back(colors[0]);
GradientShaderBase::GradientShaderBase(const std::vector<Color4f>& colors,
const std::vector<float>& positions,
const Matrix& pointsToUnit)
: pointsToUnit(pointsToUnit) {
colorsAreOpaque = true;
for (auto& color : colors) {
if (!color.isOpaque()) {
colorsAreOpaque = false;
break;
}
originalColors.insert(originalColors.end(), colors.begin(), colors.end());
if (dummyLast) {
originalColors.push_back(colors[colors.size() - 1]);
}
auto dummyFirst = false;
auto dummyLast = false;
if (!positions.empty()) {
dummyFirst = positions[0] != 0;
dummyLast = positions[positions.size() - 1] != 1.0f;
}
// Now copy over the colors, adding the dummies as needed
if (dummyFirst) {
originalColors.push_back(colors[0]);
}
originalColors.insert(originalColors.end(), colors.begin(), colors.end());
if (dummyLast) {
originalColors.push_back(colors[colors.size() - 1]);
}
if (positions.empty()) {
auto posScale = 1.0f / static_cast<float>(positions.size() - 1);
for (size_t i = 0; i < positions.size(); i++) {
originalPositions.push_back(static_cast<float>(i) * posScale);
}
if (positions.empty()) {
auto posScale = 1.0f / static_cast<float>(positions.size() - 1);
for (size_t i = 0; i < positions.size(); i++) {
originalPositions.push_back(static_cast<float>(i) * posScale);
}
} else {
float prev = 0;
originalPositions.push_back(prev); // force the first pos to 0
for (size_t i = dummyFirst ? 0 : 1; i < colors.size() + dummyLast; ++i) {
// Pin the last value to 1.0, and make sure position is monotonic.
float curr;
if (i != colors.size()) {
curr = std::max(std::min(positions[i], 1.0f), prev);
} else {
curr = 1.0f;
}
originalPositions.push_back(curr);
prev = curr;
} else {
float prev = 0;
originalPositions.push_back(prev); // force the first pos to 0
for (size_t i = dummyFirst ? 0 : 1; i < colors.size() + dummyLast; ++i) {
// Pin the last value to 1.0, and make sure position is monotonic.
float curr;
if (i != colors.size()) {
curr = std::max(std::min(positions[i], 1.0f), prev);
} else {
curr = 1.0f;
}
originalPositions.push_back(curr);
prev = curr;
}
}

bool isOpaque() const override {
return colorsAreOpaque;
}

std::vector<Color4f> originalColors = {};
std::vector<float> originalPositions = {};

protected:
const Matrix pointsToUnit;
bool colorsAreOpaque = false;
};
}

// Combines the colorizer and layout with an appropriately configured master effect based on the
// gradient's tile mode
Expand Down Expand Up @@ -213,19 +200,17 @@ static Matrix PointsToUnitMatrix(const Point& startPoint, const Point& endPoint)
return matrix;
}

class LinearGradient : public GradientShaderBase {
public:
LinearGradient(const Point& startPoint, const Point& endPoint, const std::vector<Color4f>& colors,
const std::vector<float>& positions)
: GradientShaderBase(colors, positions, PointsToUnitMatrix(startPoint, endPoint)) {
}
LinearGradient::LinearGradient(const Point& startPoint, const Point& endPoint,
const std::vector<Color4f>& colors,
const std::vector<float>& positions)
: GradientShaderBase(colors, positions, PointsToUnitMatrix(startPoint, endPoint)) {
}

std::unique_ptr<FragmentProcessor> asFragmentProcessor(const FPArgs& args) const override {
auto matrix = args.localMatrix;
matrix.postConcat(pointsToUnit);
return MakeGradient(args.context, *this, LinearGradientLayout::Make(matrix));
}
};
std::unique_ptr<FragmentProcessor> LinearGradient::asFragmentProcessor(const FPArgs& args) const {
auto matrix = args.localMatrix;
matrix.postConcat(pointsToUnit);
return MakeGradient(args.context, *this, LinearGradientLayout::Make(matrix));
}

static Matrix RadialToUnitMatrix(const Point& center, float radius) {
float inv = 1 / radius;
Expand All @@ -234,21 +219,19 @@ static Matrix RadialToUnitMatrix(const Point& center, float radius) {
return matrix;
}

class RadialGradient : public GradientShaderBase {
public:
RadialGradient(const Point& center, float radius, const std::vector<Color4f>& colors,
const std::vector<float>& positions)
: GradientShaderBase(colors, positions, RadialToUnitMatrix(center, radius)) {
}
RadialGradient::RadialGradient(const Point& center, float radius,
const std::vector<Color4f>& colors,
const std::vector<float>& positions)
: GradientShaderBase(colors, positions, RadialToUnitMatrix(center, radius)) {
}

std::unique_ptr<FragmentProcessor> asFragmentProcessor(const FPArgs& args) const override {
auto matrix = args.localMatrix;
matrix.postConcat(pointsToUnit);
return MakeGradient(args.context, *this, RadialGradientLayout::Make(matrix));
}
};
std::unique_ptr<FragmentProcessor> RadialGradient::asFragmentProcessor(const FPArgs& args) const {
auto matrix = args.localMatrix;
matrix.postConcat(pointsToUnit);
return MakeGradient(args.context, *this, RadialGradientLayout::Make(matrix));
}

std::shared_ptr<Shader> GradientShader::MakeLinear(const Point& startPoint, const Point& endPoint,
std::shared_ptr<Shader> Shader::MakeLinearGradient(const Point& startPoint, const Point& endPoint,
const std::vector<Color4f>& colors,
const std::vector<float>& positions) {
if (!std::isfinite(Point::Distance(endPoint, startPoint))) {
Expand All @@ -270,7 +253,7 @@ std::shared_ptr<Shader> GradientShader::MakeLinear(const Point& startPoint, cons
return std::make_shared<LinearGradient>(startPoint, endPoint, colors, positions);
}

std::shared_ptr<Shader> GradientShader::MakeRadial(const Point& center, float radius,
std::shared_ptr<Shader> Shader::MakeRadialGradient(const Point& center, float radius,
const std::vector<Color4f>& colors,
const std::vector<float>& positions) {
if (radius < 0) {
Expand Down
57 changes: 57 additions & 0 deletions tgfx/src/gpu/gradients/GradientShader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making libpag available.
//
// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// unless required by applicable law or agreed to in writing, software distributed under the
// license is distributed on an "as is" basis, without warranties or conditions of any kind,
// either express or implied. see the license for the specific language governing permissions
// and limitations under the license.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "gpu/ShaderBase.h"

namespace pag {

class GradientShaderBase : public ShaderBase {
public:
GradientShaderBase(const std::vector<Color4f>& colors, const std::vector<float>& positions,
const Matrix& pointsToUnit);

bool isOpaque() const override {
return colorsAreOpaque;
}

std::vector<Color4f> originalColors = {};
std::vector<float> originalPositions = {};

protected:
const Matrix pointsToUnit;
bool colorsAreOpaque = false;
};

class LinearGradient : public GradientShaderBase {
public:
LinearGradient(const Point& startPoint, const Point& endPoint, const std::vector<Color4f>& colors,
const std::vector<float>& positions);

std::unique_ptr<FragmentProcessor> asFragmentProcessor(const FPArgs& args) const override;
};

class RadialGradient : public GradientShaderBase {
public:
RadialGradient(const Point& center, float radius, const std::vector<Color4f>& colors,
const std::vector<float>& positions);

std::unique_ptr<FragmentProcessor> asFragmentProcessor(const FPArgs& args) const override;
};
} // namespace pag
1 change: 0 additions & 1 deletion tgfx/src/gpu/opengl/GLCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include "core/Blend.h"
#include "core/Mask.h"
#include "gpu/Canvas.h"
#include "gpu/GradientShader.h"

namespace pag {
class GLCanvas : public Canvas {
Expand Down

0 comments on commit 230cdb6

Please sign in to comment.