blob: c5020054644bc8c5d7d9543fff97434063a7fd15 [file] [log] [blame] [edit]
#include "rive/artboard.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/shapes/paint/stroke_cap.hpp"
#include "rive/shapes/paint/stroke_effect.hpp"
#include "rive/shapes/paint/stroke_join.hpp"
using namespace rive;
PathFlags Stroke::pathFlags() const
{
return transformAffectsStroke() ? PathFlags::local : PathFlags::world;
}
RenderPaint* Stroke::initRenderPaint(ShapePaintMutator* mutator)
{
auto renderPaint = Super::initRenderPaint(mutator);
renderPaint->style(RenderPaintStyle::stroke);
renderPaint->thickness(thickness());
renderPaint->cap((StrokeCap)cap());
renderPaint->join((StrokeJoin)join());
return renderPaint;
}
void Stroke::update(ComponentDirt value)
{
Super::update(value);
if (hasDirt(value, ComponentDirt::Path) && m_Effect != nullptr)
{
auto container = ShapePaintContainer::from(parent());
auto path = pickPath(container);
m_Effect->updateEffect(path);
}
}
void Stroke::applyTo(RenderPaint* renderPaint, float opacityModifier)
{
renderPaint->style(RenderPaintStyle::stroke);
renderPaint->thickness(thickness());
renderPaint->cap((StrokeCap)cap());
renderPaint->join((StrokeJoin)join());
renderPaint->shader(nullptr);
m_PaintMutator->applyTo(renderPaint, opacityModifier);
}
bool Stroke::isVisible() const
{
return Super::isVisible() && thickness() > 0.0f;
}
void Stroke::thicknessChanged()
{
assert(m_RenderPaint != nullptr);
m_RenderPaint->thickness(thickness());
}
void Stroke::capChanged()
{
assert(m_RenderPaint != nullptr);
m_RenderPaint->cap((StrokeCap)cap());
}
void Stroke::joinChanged()
{
assert(m_RenderPaint != nullptr);
m_RenderPaint->join((StrokeJoin)join());
}
void Stroke::addStrokeEffect(StrokeEffect* effect) { m_Effect = effect; }
void Stroke::invalidateEffects()
{
if (m_Effect != nullptr)
{
m_Effect->invalidateEffect();
}
invalidateRendering();
}
void Stroke::invalidateRendering()
{
assert(m_RenderPaint != nullptr);
m_RenderPaint->invalidateStroke();
addDirt(ComponentDirt::Path);
}
ShapePaintPath* Stroke::pickPath(ShapePaintContainer* shape) const
{
if (transformAffectsStroke())
{
return shape->localPath();
}
return shape->worldPath();
}
void Stroke::draw(Renderer* renderer,
ShapePaintPath* shapePaintPath,
const Mat2D& transform,
bool usePathFillRule,
RenderPaint* overridePaint)
{
if (m_Effect != nullptr)
{
shapePaintPath = m_Effect->effectPath();
}
Super::draw(renderer,
shapePaintPath,
transform,
usePathFillRule,
overridePaint);
}
void Stroke::buildDependencies()
{
auto container = ShapePaintContainer::from(parent());
if (container != nullptr)
{
container->pathBuilder()->addDependent(this);
}
}