| #include "rive/shapes/paint/feather.hpp" |
| #include "rive/shapes/paint/shape_paint.hpp" |
| #include "rive/shapes/paint/fill.hpp" |
| #include "rive/shapes/shape.hpp" |
| #include "rive/artboard.hpp" |
| |
| #include "rive/core_context.hpp" |
| |
| using namespace rive; |
| |
| bool Feather::validate(CoreContext* context) |
| { |
| if (!Super::validate(context)) |
| { |
| return false; |
| } |
| auto coreObject = context->resolve(parentId()); |
| // we know it's not nullptr from Super::validate |
| assert(coreObject != nullptr); |
| return coreObject->is<ShapePaint>(); |
| } |
| |
| StatusCode Feather::onAddedDirty(CoreContext* context) |
| { |
| auto code = Super::onAddedDirty(context); |
| |
| parent()->as<ShapePaint>()->feather(this); |
| return code; |
| } |
| |
| void Feather::update(ComponentDirt value) |
| { |
| auto shapePaint = parent()->as<ShapePaint>(); |
| if (hasDirt(value, ComponentDirt::Paint)) |
| { |
| auto renderPaint = shapePaint->renderPaint(); |
| renderPaint->feather(strength()); |
| } |
| |
| if (hasDirt(value, ComponentDirt::WorldTransform | ComponentDirt::Path)) |
| { |
| bool offsetInArtboard = space() == TransformSpace::world; |
| if (inner()) |
| { |
| auto shape = ShapePaintContainer::from(shapePaint->parent()); |
| |
| if (shape != nullptr) |
| { |
| auto transform = shape->shapeWorldTransform(); |
| auto path = shapePaint->pickPath(shape); |
| if (path == nullptr) |
| { |
| return; |
| } |
| auto bounds = path->rawPath()->bounds().pad(strength() * 1.5f); |
| Vec2D innerOffset(offsetX(), offsetY()); |
| if (offsetInArtboard) |
| { |
| Mat2D inverseTransform = transform.invertOrIdentity(); |
| innerOffset = |
| Vec2D::transformDir(innerOffset, inverseTransform); |
| } |
| m_innerPath.rewind(); |
| m_innerPath.addRect(bounds); |
| Mat2D innerOffsetTransform = |
| Mat2D::fromTranslation(innerOffset); |
| m_innerPath.addPathBackwards(*path->rawPath(), |
| &innerOffsetTransform); |
| } |
| #ifdef TESTING |
| renderCount++; |
| #endif |
| return; |
| } |
| } |
| } |
| |
| void Feather::buildDependencies() |
| { |
| auto shape = parent()->as<ShapePaint>()->parent(); |
| if (shape == nullptr) |
| { |
| return; |
| } |
| if (shape->is<Shape>()) |
| { |
| shape->as<Shape>()->pathComposer()->addDependent(this); |
| } |
| else |
| { |
| shape->addDependent(this); |
| } |
| } |
| |
| void Feather::strengthChanged() |
| { |
| addDirt(inner() ? (ComponentDirt)(ComponentDirt::Paint | |
| ComponentDirt::WorldTransform) |
| : ComponentDirt::Paint); |
| } |
| void Feather::offsetXChanged() { strengthChanged(); } |
| void Feather::offsetYChanged() { strengthChanged(); } |