blob: e152351eb532e46b928e1897ada5841e95793553 [file] [log] [blame]
/*
* Copyright 2022 Rive
*/
#include <rive/math/aabb.hpp>
#include <rive/math/raw_path.hpp>
#include "no_op_renderer.hpp"
#include <catch.hpp>
#include <cstdio>
using namespace rive;
TEST_CASE("rawpath-basics", "[rawpath]") {
RawPath path;
REQUIRE(path.empty());
REQUIRE(path.bounds() == AABB{0, 0, 0, 0});
path.move({1, 2});
REQUIRE(!path.empty());
REQUIRE(path.bounds() == AABB{1, 2, 1, 2});
path = RawPath();
REQUIRE(path.empty());
REQUIRE(path.bounds() == AABB{0, 0, 0, 0});
path.move({1, -2});
path.line({3, 4});
path.line({-1, 5});
REQUIRE(!path.empty());
REQUIRE(path.bounds() == AABB{-1, -2, 3, 5});
}
TEST_CASE("rawpath-add-helpers", "[rawpath]") {
RawPath path;
path.addRect({1, 1, 5, 6});
REQUIRE(!path.empty());
REQUIRE(path.bounds() == AABB{1, 1, 5, 6});
REQUIRE(path.points().size() == 4);
REQUIRE(path.verbs().size() == 5); // move, line, line, line, close
path = RawPath();
path.addOval({0, 0, 3, 6});
REQUIRE(!path.empty());
REQUIRE(path.bounds() == AABB{0, 0, 3, 6});
REQUIRE(path.points().size() == 13);
REQUIRE(path.verbs().size() == 6); // move, cubic, cubic, cubic, cubic, close
const Vec2D pts[] = {
{1, 2},
{4, 5},
{3, 2},
{100, -100},
};
constexpr auto size = sizeof(pts) / sizeof(pts[0]);
for (auto isClosed : {false, true}) {
path = RawPath();
path.addPoly({pts, size}, isClosed);
REQUIRE(path.bounds() == AABB{1, -100, 100, 5});
REQUIRE(path.points().size() == size);
REQUIRE(path.verbs().size() == size + isClosed);
for (size_t i = 0; i < size; ++i) {
REQUIRE(path.points()[i] == pts[i]);
}
REQUIRE(path.verbs()[0] == PathVerb::move);
for (size_t i = 1; i < size; ++i) {
REQUIRE(path.verbs()[i] == PathVerb::line);
}
if (isClosed) {
REQUIRE(path.verbs()[size] == PathVerb::close);
}
}
}
//////////////////////////////////////////////////////////////////////////
static bool is_move(const RawPath::Iter::Rec& rec) {
if (rec.verb == PathVerb::move) {
REQUIRE(rec.count == 1);
return true;
}
return false;
}
static bool is_line(const RawPath::Iter::Rec& rec) {
if (rec.verb == PathVerb::line) {
REQUIRE(rec.count == 1);
return true;
}
return false;
}
static bool is_quad(const RawPath::Iter::Rec& rec) {
if (rec.verb == PathVerb::quad) {
REQUIRE(rec.count == 2);
return true;
}
return false;
}
static bool is_cubic(const RawPath::Iter::Rec& rec) {
if (rec.verb == PathVerb::cubic) {
REQUIRE(rec.count == 3);
return true;
}
return false;
}
static bool is_close(const RawPath::Iter::Rec& rec) {
if (rec.verb == PathVerb::close) {
REQUIRE(rec.count == 0);
return true;
}
return false;
}
TEST_CASE("rawpath-iter", "[rawpath]") {
auto eq = [](Vec2D p, float x, float y) { return p.x == x && p.y == y; };
{
RawPath rp;
RawPath::Iter iter(rp);
REQUIRE(iter.next() == false);
REQUIRE(iter.next() == false); // should be safe to call again
}
{
RawPath rp;
rp.moveTo(1, 2);
rp.lineTo(3, 4);
rp.quadTo(5, 6, 7, 8);
rp.cubicTo(9, 10, 11, 12, 13, 14);
rp.close();
RawPath::Iter iter(rp);
auto rec = iter.next();
REQUIRE((rec && is_move(rec) && eq(rec.pts[0], 1,2)));
rec = iter.next();
REQUIRE((rec && is_line(rec) && eq(rec.pts[0], 3,4)));
rec = iter.next();
REQUIRE((rec && is_quad(rec) && eq(rec.pts[0], 5,6)
&& eq(rec.pts[1], 7,8)));
rec = iter.next();
REQUIRE((rec && is_cubic(rec) && eq(rec.pts[0], 9,10)
&& eq(rec.pts[1], 11,12)
&& eq(rec.pts[2], 13,14)));
rec = iter.next();
REQUIRE((rec && is_close(rec)));
rec = iter.next();
REQUIRE(rec == false);
REQUIRE(iter.next() == false); // should be safe to call again
}
}