mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00

Remove the requirement for unique_ptr in the function prototypes. This change will simplify the API usage, making it more streamlined and user-friendly. However, memory management will now be the responsibility of the user. C++ API Modification: - Result Paint::mask(std::unique_ptr<Paint> target, MaskMethod method) -> Result Paint::mask(Paint* target, MaskMethod method) - Result Paint::clip(std::unique_ptr<Paint> clipper) -> Result Paint::clip(Paint* clipper) - virtual Result Canvas::push(std::unique_ptr<Paint> paint) -> virtual Result Canvas::push(Paint* paint) - std::unique_ptr<LinearGradient> LinearGradient::gen() -> LinearGradient* LinearGradient::gen() - std::unique_ptr<RadialGradient> RadialGradient::gen() -> RadialGradient* RadialGradient::gen() - Result Shape::strokeFill(std::unique_ptr<Fill> f) -> Result Shape::strokeFill(Fill* f) - Result Shape::fill(std::unique_ptr<Fill> f) -> Result Shape::fill(Fill* f) - std::unique_ptr<Shape> Shape::gen() -> Shape* Shape::gen() - std::unique_ptr<Picture> Picture::gen() -> Result Picture::push(Paint* paint) - std::unique_ptr<Scene> Scene::gen() -> Scene* Scene::gen() - Result Text::fill(std::unique_ptr<Fill> f) -> Result Text::fill(Fill* f) - std::unique_ptr<Text> Text::gen() -> Text* Text::gen() - std::unique_ptr<SwCanvas> SwCanvas::gen() -> SwCanvas* SwCanvas::gen() - std::unique_ptr<GlCanvas> GlCanvas::gen() -> GlCanvas* GlCanvas::gen() - std::unique_ptr<Animation> Animation::gen() -> Animation* Animation::gen() - Result Saver::background(std::unique_ptr<Paint> paint) -> Result Saver::background(Paint* paint) - Result Saver::save(std::unique_ptr<Paint> paint, const char* filename, uint32_t quality = 100) -> Result Saver::save(Paint* paint, const char* filename, uint32_t quality = 100) - std::unique_ptr<Saver> Saver::gen() -> Saver* Saver::gen() - std::unique_ptr<Accessor> Accessor::gen() -> Accessor* Accessor::gen() C++ API removal: - template<typename T = tvg::Paint> std::unique_ptr<T> cast(Paint* paint) - template<typename T = tvg::Paint> std::unique_ptr<T> cast(Paint* paint) issue: https://github.com/thorvg/thorvg/issues
290 lines
9.8 KiB
C++
290 lines
9.8 KiB
C++
/*
|
|
* Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include <thorvg.h>
|
|
#include "config.h"
|
|
#include "catch.hpp"
|
|
|
|
using namespace tvg;
|
|
using namespace std;
|
|
|
|
|
|
TEST_CASE("Filling Creation", "[tvgFill]")
|
|
{
|
|
auto linear = unique_ptr<LinearGradient>(LinearGradient::gen());
|
|
REQUIRE(linear);
|
|
|
|
REQUIRE(linear->type() == Type::LinearGradient);
|
|
|
|
auto radial = unique_ptr<RadialGradient>(RadialGradient::gen());
|
|
REQUIRE(radial);
|
|
|
|
REQUIRE(radial->type() == Type::RadialGradient);
|
|
}
|
|
|
|
TEST_CASE("Common Filling", "[tvgFill]")
|
|
{
|
|
auto fill = LinearGradient::gen();
|
|
REQUIRE(fill);
|
|
|
|
//Options
|
|
REQUIRE(fill->spread() == FillSpread::Pad);
|
|
REQUIRE(fill->spread(FillSpread::Pad) == Result::Success);
|
|
REQUIRE(fill->spread(FillSpread::Reflect) == Result::Success);
|
|
REQUIRE(fill->spread(FillSpread::Repeat) == Result::Success);
|
|
REQUIRE(fill->spread() == FillSpread::Repeat);
|
|
|
|
//ColorStops
|
|
const Fill::ColorStop* cs = nullptr;
|
|
REQUIRE(fill->colorStops(nullptr) == 0);
|
|
REQUIRE(fill->colorStops(&cs) == 0);
|
|
REQUIRE(cs == nullptr);
|
|
|
|
Fill::ColorStop cs2[4] = {
|
|
{0.0f, 0, 0, 0, 0},
|
|
{0.2f, 50, 25, 50, 25},
|
|
{0.5f, 100, 100, 100, 125},
|
|
{1.0f, 255, 255, 255, 255}
|
|
};
|
|
|
|
REQUIRE(fill->colorStops(nullptr, 4) == Result::InvalidArguments);
|
|
REQUIRE(fill->colorStops(cs2, 0) == Result::InvalidArguments);
|
|
REQUIRE(fill->colorStops(cs2, 4) == Result::Success);
|
|
REQUIRE(fill->colorStops(&cs) == 4);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
REQUIRE(cs[i].offset == cs2[i].offset);
|
|
REQUIRE(cs[i].r == cs2[i].r);
|
|
REQUIRE(cs[i].g == cs2[i].g);
|
|
REQUIRE(cs[i].b == cs2[i].b);
|
|
};
|
|
|
|
//Reset ColorStop
|
|
REQUIRE(fill->colorStops(nullptr, 0) == Result::Success);
|
|
REQUIRE(fill->colorStops(&cs) == 0);
|
|
|
|
//Set to Shape
|
|
auto shape = unique_ptr<Shape>(Shape::gen());
|
|
REQUIRE(shape);
|
|
|
|
REQUIRE(shape->fill(fill) == Result::Success);
|
|
REQUIRE(shape->fill() == fill);
|
|
}
|
|
|
|
TEST_CASE("Fill Transformation", "[tvgFill]")
|
|
{
|
|
auto fill = unique_ptr<LinearGradient>(LinearGradient::gen());
|
|
REQUIRE(fill);
|
|
|
|
//no transformation
|
|
auto mGet = fill->transform();
|
|
REQUIRE(mGet.e11 == Approx(1.0f).margin(0.000001));
|
|
REQUIRE(mGet.e12 == Approx(0.0f).margin(0.000001));
|
|
REQUIRE(mGet.e13 == Approx(0.0f).margin(0.000001));
|
|
REQUIRE(mGet.e21 == Approx(0.0f).margin(0.000001));
|
|
REQUIRE(mGet.e22 == Approx(1.0f).margin(0.000001));
|
|
REQUIRE(mGet.e23 == Approx(0.0f).margin(0.000001));
|
|
REQUIRE(mGet.e31 == Approx(0.0f).margin(0.000001));
|
|
REQUIRE(mGet.e32 == Approx(0.0f).margin(0.000001));
|
|
REQUIRE(mGet.e33 == Approx(1.0f).margin(0.000001));
|
|
|
|
auto mSet = Matrix{1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, -7.7f, -8.8f, -9.9f};
|
|
REQUIRE(fill->transform(mSet) == Result::Success);
|
|
|
|
//transformation was set
|
|
mGet = fill->transform();
|
|
REQUIRE(mGet.e11 == Approx(mSet.e11).margin(0.000001));
|
|
REQUIRE(mGet.e12 == Approx(mSet.e12).margin(0.000001));
|
|
REQUIRE(mGet.e13 == Approx(mSet.e13).margin(0.000001));
|
|
REQUIRE(mGet.e21 == Approx(mSet.e21).margin(0.000001));
|
|
REQUIRE(mGet.e22 == Approx(mSet.e22).margin(0.000001));
|
|
REQUIRE(mGet.e23 == Approx(mSet.e23).margin(0.000001));
|
|
REQUIRE(mGet.e31 == Approx(mSet.e31).margin(0.000001));
|
|
REQUIRE(mGet.e32 == Approx(mSet.e32).margin(0.000001));
|
|
REQUIRE(mGet.e33 == Approx(mSet.e33).margin(0.000001));
|
|
}
|
|
|
|
TEST_CASE("Linear Filling", "[tvgFill]")
|
|
{
|
|
auto fill = unique_ptr<LinearGradient>(LinearGradient::gen());
|
|
REQUIRE(fill);
|
|
|
|
float x1, y1, x2, y2;
|
|
|
|
REQUIRE(fill->linear(nullptr, nullptr, nullptr, nullptr) == Result::Success);
|
|
REQUIRE(fill->linear(0, 0, 0, 0) == Result::Success);
|
|
|
|
REQUIRE(fill->linear(&x1, nullptr, &x2, nullptr) == Result::Success);
|
|
REQUIRE(x1 == 0.0f);
|
|
REQUIRE(x2 == 0.0f);
|
|
|
|
REQUIRE(fill->linear(-1.0f, -1.0f, 100.0f, 100.0f) == Result::Success);
|
|
REQUIRE(fill->linear(&x1, &y1, &x2, &y2) == Result::Success);
|
|
REQUIRE(x1 == -1.0f);
|
|
REQUIRE(y1 == -1.0f);
|
|
REQUIRE(x2 == 100.0f);
|
|
REQUIRE(y2 == 100.0f);
|
|
}
|
|
|
|
TEST_CASE("Radial Filling", "[tvgFill]")
|
|
{
|
|
auto fill = unique_ptr<RadialGradient>(RadialGradient::gen());
|
|
REQUIRE(fill);
|
|
|
|
float cx, cy, r, fx, fy, fr;
|
|
|
|
REQUIRE(fill->radial(0, 0, -1, 0, 0, 0) == Result::InvalidArguments);
|
|
REQUIRE(fill->radial(0, 0, 0, 0, 0, -1) == Result::InvalidArguments);
|
|
REQUIRE(fill->radial(nullptr, nullptr, nullptr) == Result::Success);
|
|
REQUIRE(fill->radial(100, 120, 50, 10, 20, 5) == Result::Success);
|
|
|
|
REQUIRE(fill->radial(&cx, nullptr, &r) == Result::Success);
|
|
REQUIRE(cx == 100.0f);
|
|
REQUIRE(r == 50.0f);
|
|
|
|
REQUIRE(fill->radial(nullptr, &cy, nullptr, &fx, &fy, &fr) == Result::Success);
|
|
REQUIRE(cy == 120);
|
|
REQUIRE(fx == 10);
|
|
REQUIRE(fy == 20);
|
|
REQUIRE(fr == 5);
|
|
|
|
REQUIRE(fill->radial(0, 0, 0, 0, 0, 0) == Result::Success);
|
|
REQUIRE(fill->radial(&cx, &cy, &r, &fx, &fy, &fr) == Result::Success);
|
|
REQUIRE(cx == 0.0f);
|
|
REQUIRE(cy == 0.0f);
|
|
REQUIRE(r == 0.0f);
|
|
REQUIRE(fx == 0.0f);
|
|
REQUIRE(fy == 0.0f);
|
|
REQUIRE(fr == 0.0f);
|
|
}
|
|
|
|
TEST_CASE("Linear Filling Duplication", "[tvgFill]")
|
|
{
|
|
auto fill = unique_ptr<LinearGradient>(LinearGradient::gen());
|
|
REQUIRE(fill);
|
|
|
|
//Setup
|
|
Fill::ColorStop cs[4] = {
|
|
{0.0f, 0, 0, 0, 0},
|
|
{0.2f, 50, 25, 50, 25},
|
|
{0.5f, 100, 100, 100, 125},
|
|
{1.0f, 255, 255, 255, 255}
|
|
};
|
|
|
|
REQUIRE(fill->colorStops(cs, 4) == Result::Success);
|
|
REQUIRE(fill->spread(FillSpread::Reflect) == Result::Success);
|
|
REQUIRE(fill->linear(-10.0f, 10.0f, 100.0f, 120.0f) == Result::Success);
|
|
|
|
auto m = Matrix{1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, -7.7f, -8.8f, -9.9f};
|
|
REQUIRE(fill->transform(m) == Result::Success);
|
|
|
|
//Duplication
|
|
auto dup = unique_ptr<LinearGradient>((LinearGradient*)fill->duplicate());
|
|
REQUIRE(dup);
|
|
|
|
REQUIRE(dup->spread() == FillSpread::Reflect);
|
|
|
|
float x1, y1, x2, y2;
|
|
REQUIRE(fill->linear(&x1, &y1, &x2, &y2) == Result::Success);
|
|
REQUIRE(x1 == -10.0f);
|
|
REQUIRE(y1 == 10.0f);
|
|
REQUIRE(x2 == 100.0f);
|
|
REQUIRE(y2 == 120.0f);
|
|
|
|
const Fill::ColorStop* cs2 = nullptr;
|
|
REQUIRE(fill->colorStops(&cs2) == 4);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
REQUIRE(cs[i].offset == cs2[i].offset);
|
|
REQUIRE(cs[i].r == cs2[i].r);
|
|
REQUIRE(cs[i].g == cs2[i].g);
|
|
REQUIRE(cs[i].b == cs2[i].b);
|
|
}
|
|
|
|
auto mDup = dup->transform();
|
|
REQUIRE(mDup.e11 == Approx(m.e11).margin(0.000001));
|
|
REQUIRE(mDup.e12 == Approx(m.e12).margin(0.000001));
|
|
REQUIRE(mDup.e13 == Approx(m.e13).margin(0.000001));
|
|
REQUIRE(mDup.e21 == Approx(m.e21).margin(0.000001));
|
|
REQUIRE(mDup.e22 == Approx(m.e22).margin(0.000001));
|
|
REQUIRE(mDup.e23 == Approx(m.e23).margin(0.000001));
|
|
REQUIRE(mDup.e31 == Approx(m.e31).margin(0.000001));
|
|
REQUIRE(mDup.e32 == Approx(m.e32).margin(0.000001));
|
|
REQUIRE(mDup.e33 == Approx(m.e33).margin(0.000001));
|
|
}
|
|
|
|
TEST_CASE("Radial Filling Duplication", "[tvgFill]")
|
|
{
|
|
auto fill = unique_ptr<RadialGradient>(RadialGradient::gen());
|
|
REQUIRE(fill);
|
|
|
|
//Setup
|
|
Fill::ColorStop cs[4] = {
|
|
{0.0f, 0, 0, 0, 0},
|
|
{0.2f, 50, 25, 50, 25},
|
|
{0.5f, 100, 100, 100, 125},
|
|
{1.0f, 255, 255, 255, 255}
|
|
};
|
|
|
|
REQUIRE(fill->colorStops(cs, 4) == Result::Success);
|
|
REQUIRE(fill->spread(FillSpread::Reflect) == Result::Success);
|
|
REQUIRE(fill->radial(100.0f, 120.0f, 50.0f, 10.0f, 20.0f, 5.0f) == Result::Success);
|
|
|
|
auto m = Matrix{1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, -7.7f, -8.8f, -9.9f};
|
|
REQUIRE(fill->transform(m) == Result::Success);
|
|
|
|
//Duplication
|
|
auto dup = unique_ptr<RadialGradient>((RadialGradient*)fill->duplicate());
|
|
REQUIRE(dup);
|
|
|
|
REQUIRE(dup->spread() == FillSpread::Reflect);
|
|
|
|
float cx, cy, r, fx, fy, fr;
|
|
REQUIRE(dup->radial(&cx, &cy, &r, &fx, &fy, &fr) == Result::Success);
|
|
REQUIRE(cx == 100.0f);
|
|
REQUIRE(cy == 120.0f);
|
|
REQUIRE(r == 50.0f);
|
|
REQUIRE(fx == 10.0f);
|
|
REQUIRE(fy == 20.0f);
|
|
REQUIRE(fr == 5.0f);
|
|
|
|
const Fill::ColorStop* cs2 = nullptr;
|
|
REQUIRE(fill->colorStops(&cs2) == 4);
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
REQUIRE(cs[i].offset == cs2[i].offset);
|
|
REQUIRE(cs[i].r == cs2[i].r);
|
|
REQUIRE(cs[i].g == cs2[i].g);
|
|
REQUIRE(cs[i].b == cs2[i].b);
|
|
}
|
|
|
|
auto mDup = dup->transform();
|
|
REQUIRE(mDup.e11 == Approx(m.e11).margin(0.000001));
|
|
REQUIRE(mDup.e12 == Approx(m.e12).margin(0.000001));
|
|
REQUIRE(mDup.e13 == Approx(m.e13).margin(0.000001));
|
|
REQUIRE(mDup.e21 == Approx(m.e21).margin(0.000001));
|
|
REQUIRE(mDup.e22 == Approx(m.e22).margin(0.000001));
|
|
REQUIRE(mDup.e23 == Approx(m.e23).margin(0.000001));
|
|
REQUIRE(mDup.e31 == Approx(m.e31).margin(0.000001));
|
|
REQUIRE(mDup.e32 == Approx(m.e32).margin(0.000001));
|
|
REQUIRE(mDup.e33 == Approx(m.e33).margin(0.000001));
|
|
}
|