blob: a46fc47cd7c33c9728612951dc8cf73783c2055b [file] [log] [blame] [edit]
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/shape_paint_container.hpp"
#include "rive/shapes/paint/feather.hpp"
#include "rive/artboard.hpp"
#include "rive/factory.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/profiler/profiler_macros.h"
using namespace rive;
StatusCode ShapePaint::onAddedClean(CoreContext* context)
{
auto container = ShapePaintContainer::from(parent());
if (container == nullptr)
{
return StatusCode::MissingObject;
}
// If the paint mutator wasn't compatible with this runtime it's possible we
// get a ShapePaint with no mutator (not children).
if (m_PaintMutator != nullptr)
{
container->addPaint(this);
}
return StatusCode::Ok;
}
RenderPaint* ShapePaint::initRenderPaint(ShapePaintMutator* mutator)
{
assert(m_RenderPaint == nullptr);
m_PaintMutator = mutator;
auto factory = mutator->component()->artboard()->factory();
m_RenderPaint = factory->makeRenderPaint();
return m_RenderPaint.get();
}
void ShapePaint::blendMode(BlendMode parentValue)
{
assert(m_RenderPaint != nullptr);
// 127 means inherit
if (blendModeValue() == 127)
{
m_RenderPaint->blendMode(parentValue);
}
else
{
m_RenderPaint->blendMode((BlendMode)blendModeValue());
}
}
void ShapePaint::feather(Feather* feather) { m_feather = feather; }
Feather* ShapePaint::feather() const { return m_feather; }
void ShapePaint::draw(Renderer* renderer,
ShapePaintPath* shapePaintPath,
const Mat2D& transform,
bool usePathFillRule,
RenderPaint* overridePaint)
{
RIVE_PROF_SCOPE()
ShapePaintPath* pathToDraw = shapePaintPath;
bool saved = false;
if (m_feather != nullptr)
{
bool offsetInArtboard = m_feather->space() == TransformSpace::world;
if (offsetInArtboard && !m_feather->inner())
{
if (m_feather->offsetX() != 0 || m_feather->offsetY() != 0)
{
if (!saved)
{
saved = true;
renderer->save();
}
renderer->translate(m_feather->offsetX(), m_feather->offsetY());
}
}
}
if (shapePaintPath->isLocal())
{
if (!saved)
{
saved = true;
renderer->save();
}
renderer->transform(transform);
}
if (m_feather != nullptr)
{
if (m_feather->inner())
{
if (m_feather->innerPath() == nullptr)
{
return;
}
pathToDraw = m_feather->innerPath();
if (!saved)
{
saved = true;
renderer->save();
}
auto renderPath = shapePaintPath->renderPath(this);
if (renderPath != nullptr)
{
renderer->clipPath(renderPath);
}
}
// If we're offseting in world space, apply the offset last.
if (m_feather->space() != TransformSpace::world &&
!m_feather->inner() &&
(m_feather->offsetX() != 0 || m_feather->offsetY() != 0))
{
if (!saved)
{
saved = true;
renderer->save();
}
renderer->translate(m_feather->offsetX(), m_feather->offsetY());
}
}
auto renderPath = pathToDraw->renderPath(this);
if (renderPath != nullptr)
{
// Ugh, can't we make fillRule part of the Paint?
if (!usePathFillRule && is<Fill>())
{
renderPath->fillRule((FillRule)as<Fill>()->fillRule());
}
renderer->drawPath(renderPath,
overridePaint != nullptr ? overridePaint
: renderPaint());
}
if (saved)
{
renderer->restore();
}
}