blob: f96e1d445b87ff3e875b46206715de8e5cf4d275 [file]
#ifndef _RIVE_TEXT_VALUE_RUN_HPP_
#define _RIVE_TEXT_VALUE_RUN_HPP_
#include "rive/generated/text/text_value_run_base.hpp"
#include "rive/text/utf.hpp"
#include "rive/text/text_style_reference.hpp"
#include "rive/math/rectangles_to_contour.hpp"
#include "rive/refcnt.hpp"
namespace rive
{
class TextStylePaint;
class Text;
class ViewModelInstanceArtboard;
class TextValueRun : public TextValueRunBase
{
friend class HitTextRun;
public:
// Out of line: m_boundStyleValue's type is only forward declared here.
TextValueRun();
~TextValueRun() override;
StatusCode onAddedClean(CoreContext* context) override;
StatusCode onAddedDirty(CoreContext* context) override;
// Resolves lazily so a global style whose nested-artboard instance is
// created after this run is added still returns the current paint.
TextStylePaint* style()
{
return m_styleReference != nullptr ? m_styleReference->resolvedPaint()
: nullptr;
}
void style(TextStyleReference* value) { m_styleReference = value; }
TextStyleReference* styleReference() const { return m_styleReference; }
/// Draws the global text style [value] (a text style view model value)
/// names in place of the authored one, while a data bind on styleId holds
/// it (see Text::boundRunStyle). styleId keeps the authored style, which a
/// value naming no text style falls back to.
void bindStyle(ViewModelInstanceArtboard* value);
bool isStyleBound() const { return m_boundStyleValue != nullptr; }
/// Resolves the style the run draws again: the bound one, else the
/// authored one.
void resolveStyle();
Text* textComponent() const;
void textComponent(Text* value) { m_textComponent = value; };
uint32_t length()
{
if (m_length == -1)
{
const uint8_t* ptr = (const uint8_t*)text().data();
const uint8_t* end = ptr + text().size();
uint32_t n = 0;
while (ptr < end && *ptr)
{
UTF::NextUTF8(&ptr, end);
n += 1;
}
m_length = n;
}
return m_length;
}
uint32_t offset() const;
// Reset stored data for hit testing the run.
void resetHitTest();
// Add a rectangle (usually bounding a glyph) as a hit rect that will be
// used to compute contours when computeHitContours is called.
void addHitRect(const AABB& rect);
// Compute the contours used for hit testing, call resetHitTest to start
// adding hit rects (via addHitRect) again.
void computeHitContours();
bool hitTestAABB(const Vec2D& position);
bool hitTestHiFi(const Vec2D& position, float hitRadius);
bool isHitTarget() const { return m_isHitTarget; }
void isHitTarget(bool value);
bool hitTestPoint(
const Vec2D& position,
bool skipOnUnclipped,
bool isPrimaryHit) override;
protected:
void textChanged() override;
void styleIdChanged() override;
private:
std::unique_ptr<RectanglesToContour> m_rectanglesToContour;
AABB m_localBounds;
bool m_isHitTarget = false;
std::vector<AABB> m_glyphHitRects;
TextStyleReference* m_styleReference = nullptr;
// The text style view model value a data bind on styleId holds, if any.
rcp<ViewModelInstanceArtboard> m_boundStyleValue;
uint32_t m_length = -1;
bool canHitTest() const;
TextStyleReference* authoredStyle() const;
Text* m_textComponent = nullptr;
};
} // namespace rive
#endif