blob: 78fbb3031607add2e731861e274b806a9750cae1 [file] [log] [blame]
#include "rive/shapes/shape.hpp"
#include "rive/shapes/clipping_shape.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/path_composer.hpp"
#include <algorithm>
using namespace rive;
Shape::Shape() : m_PathComposer(this) {}
void Shape::addPath(Path* path) {
// Make sure the path is not already in the shape.
assert(std::find(m_Paths.begin(), m_Paths.end(), path) == m_Paths.end());
m_Paths.push_back(path);
}
void Shape::update(ComponentDirt value) {
Super::update(value);
if (hasDirt(value, ComponentDirt::RenderOpacity)) {
for (auto shapePaint : m_ShapePaints) {
shapePaint->renderOpacity(renderOpacity());
}
}
}
void Shape::pathChanged() {
m_PathComposer.addDirt(ComponentDirt::Path, true);
invalidateStrokeEffects();
}
void Shape::draw(Renderer* renderer) {
if (renderOpacity() == 0.0f) {
return;
}
auto shouldRestore = clip(renderer);
for (auto shapePaint : m_ShapePaints) {
if (!shapePaint->isVisible()) {
continue;
}
renderer->save();
bool paintsInLocal =
(shapePaint->pathSpace() & PathSpace::Local) == PathSpace::Local;
if (paintsInLocal) {
renderer->transform(worldTransform());
}
shapePaint->draw(renderer,
paintsInLocal ? m_PathComposer.localPath()
: m_PathComposer.worldPath());
renderer->restore();
}
if (shouldRestore) {
renderer->restore();
}
}
void Shape::buildDependencies() {
// Make sure to propagate the call to PathComposer as it's no longer part of
// Core and owned only by the Shape.
m_PathComposer.buildDependencies();
Super::buildDependencies();
// Set the blend mode on all the shape paints. If we ever animate this
// property, we'll need to update it in the update cycle/mark dirty when the
// blend mode changes.
for (auto paint : m_ShapePaints) {
paint->blendMode(blendMode());
}
}
void Shape::addDefaultPathSpace(PathSpace space) {
m_DefaultPathSpace |= space;
}
StatusCode Shape::onAddedDirty(CoreContext* context) {
auto code = Super::onAddedDirty(context);
if (code != StatusCode::Ok) {
return code;
}
// This ensures context propagates to path composer too.
return m_PathComposer.onAddedDirty(context);
}