blob: 5082f6d6c90be927a92518cc022beb51dcd53df7 [file] [log] [blame]
#include "rive/core/type_conversions.hpp"
#include "rive/shapes/metrics_path.hpp"
#include "rive/renderer.hpp"
#include "rive/math/cubic_utilities.hpp"
#include "rive/math/raw_path.hpp"
#include "rive/math/contour_measure.hpp"
using namespace rive;
void MetricsPath::reset() {
m_Paths.clear();
m_Contour.reset(nullptr);
m_RawPath = RawPath();
m_ComputedLengthTransform = Mat2D();
m_ComputedLength = 0;
}
void MetricsPath::addPath(CommandPath* path, const Mat2D& transform) {
MetricsPath* metricsPath = reinterpret_cast<MetricsPath*>(path);
m_ComputedLength += metricsPath->computeLength(transform);
m_Paths.emplace_back(metricsPath);
}
void MetricsPath::moveTo(float x, float y) {
assert(m_RawPath.points().size() == 0);
m_RawPath.move({x, y});
}
void MetricsPath::lineTo(float x, float y) { m_RawPath.line({x, y}); }
void MetricsPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y) {
m_RawPath.cubic({ox, oy}, {ix, iy}, {x, y});
}
void MetricsPath::close() {
// Should we pass the close() to our m_RawPath ???
}
float MetricsPath::computeLength(const Mat2D& transform) {
// Only compute if our pre-computed length is not valid
if (!m_Contour || transform != m_ComputedLengthTransform) {
m_ComputedLengthTransform = transform;
m_Contour = ContourMeasureIter(m_RawPath * transform).next();
m_ComputedLength = m_Contour ? m_Contour->length() : 0;
}
return m_ComputedLength;
}
void MetricsPath::trim(float startLength, float endLength, bool moveTo, RenderPath* result) {
assert(endLength >= startLength);
if (!m_Paths.empty()) {
m_Paths.front()->trim(startLength, endLength, moveTo, result);
return;
}
// TODO: if we can change the signature of MetricsPath and/or trim() to speak native
// rawpaths, we wouldn't need this temporary copy (since ContourMeasure speaks
// native rawpaths).
RawPath tmp;
m_Contour->getSegment(startLength, endLength, &tmp, moveTo);
tmp.addTo(result);
}
RenderMetricsPath::RenderMetricsPath(std::unique_ptr<RenderPath> path) :
m_RenderPath(std::move(path)) {}
void RenderMetricsPath::addPath(CommandPath* path, const Mat2D& transform) {
MetricsPath::addPath(path, transform);
m_RenderPath->addPath(path->renderPath(), transform);
}
void RenderMetricsPath::reset() {
MetricsPath::reset();
m_RenderPath->reset();
}
void RenderMetricsPath::moveTo(float x, float y) {
MetricsPath::moveTo(x, y);
m_RenderPath->moveTo(x, y);
}
void RenderMetricsPath::lineTo(float x, float y) {
MetricsPath::lineTo(x, y);
m_RenderPath->lineTo(x, y);
}
void RenderMetricsPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y) {
MetricsPath::cubicTo(ox, oy, ix, iy, x, y);
m_RenderPath->cubicTo(ox, oy, ix, iy, x, y);
}
void RenderMetricsPath::close() {
MetricsPath::close();
m_RenderPath->close();
}
void RenderMetricsPath::fillRule(FillRule value) { m_RenderPath->fillRule(value); }