blob: cab469d5a2d0b1cd1ef4221da0fb7ba140344159 [file] [log] [blame] [edit]
#ifndef _RIVE_CLIPPING_SHAPE_HPP_
#define _RIVE_CLIPPING_SHAPE_HPP_
#include "rive/renderer.hpp"
#include "rive/generated/shapes/clipping_shape_base.hpp"
#include "rive/shapes/shape_paint_path.hpp"
#include "rive/drawable.hpp"
#include <vector>
namespace rive
{
class Shape;
class Node;
class RenderPath;
class ClippingShapeStart;
class ClippingShapeEnd;
class ClippingShapeOperation
{
public:
virtual ~ClippingShapeOperation() = default;
virtual void draw(Renderer* renderer, bool needsSaveOperation) = 0;
virtual int emptyClipCount() = 0;
void clippingShape(ClippingShape* shape) { m_clippingShape = shape; }
virtual bool isStart() { return false; }
virtual bool isVisible() { return true; }
protected:
ClippingShape* m_clippingShape = nullptr;
};
class ClippingShapeStart : public ClippingShapeOperation
{
public:
void draw(Renderer* renderer, bool needsSaveOperation) override;
int emptyClipCount() override;
bool isStart() override { return true; }
bool isVisible() override;
};
class ClippingShapeEnd : public ClippingShapeOperation
{
void draw(Renderer* renderer, bool needsSaveOperation) override;
int emptyClipCount() override;
};
class ClippingShapeProxyDrawable : public Drawable
{
public:
ClippingShapeProxyDrawable(ClippingShapeOperation* operation) :
m_clippingShapeOperation(operation)
{}
void draw(Renderer* renderer) override
{
m_clippingShapeOperation->draw(renderer, m_needsSaveOperation);
}
int emptyClipCount() override
{
return m_clippingShapeOperation->emptyClipCount();
}
bool isHidden() const override { return false; }
Drawable* hittableComponent() override { return nullptr; };
bool isTargetOpaque() override { return false; };
Core* hitTest(HitInfo*, const Mat2D&) override { return nullptr; }
void operation(ClippingShapeOperation* value)
{
m_clippingShapeOperation = value;
}
bool isProxy() override { return true; }
bool isClipStart() override { return m_clippingShapeOperation->isStart(); }
bool isClipEnd() override { return !m_clippingShapeOperation->isStart(); }
bool willClip() override { return m_clippingShapeOperation->isVisible(); }
private:
ClippingShapeOperation* m_clippingShapeOperation = nullptr;
};
class ClippingShape : public ClippingShapeBase
{
private:
std::vector<Shape*> m_Shapes;
std::vector<ClippingShapeProxyDrawable*> m_proxyDrawables;
std::vector<ClippingShapeProxyDrawable*> m_pooledProxyDrawables;
Node* m_Source = nullptr;
public:
~ClippingShape();
Node* source() const { return m_Source; }
const std::vector<Shape*>& shapes() const { return m_Shapes; }
StatusCode onAddedClean(CoreContext* context) override;
StatusCode onAddedDirty(CoreContext* context) override;
void buildDependencies() override;
void update(ComponentDirt value) override;
void isVisibleChanged() override;
ShapePaintPath* path() { return m_clipPath; }
void resetDrawables()
{
m_pooledProxyDrawables.insert(m_pooledProxyDrawables.end(),
m_proxyDrawables.begin(),
m_proxyDrawables.end());
m_proxyDrawables.clear();
}
ClippingShapeProxyDrawable* createProxyDrawable(
ClippingShapeOperation* operation)
{
ClippingShapeProxyDrawable* drawable;
if (m_pooledProxyDrawables.size() > 0)
{
drawable = m_pooledProxyDrawables.back();
drawable->operation(operation);
drawable->needsSaveOperation(true);
m_pooledProxyDrawables.pop_back();
}
else
{
drawable = new ClippingShapeProxyDrawable(operation);
}
m_proxyDrawables.push_back(drawable);
return drawable;
}
ClippingShapeStart clipStart;
ClippingShapeEnd clipEnd;
private:
ShapePaintPath m_path;
ShapePaintPath* m_clipPath = nullptr;
};
} // namespace rive
#endif