| #ifndef _RIVE_TEXT_MODIFIER_RANGE_HPP_ |
| #define _RIVE_TEXT_MODIFIER_RANGE_HPP_ |
| #include "rive/generated/text/text_modifier_range_base.hpp" |
| #include "rive/text_engine.hpp" |
| #include <vector> |
| |
| namespace rive |
| { |
| enum class TextRangeUnits : uint8_t |
| { |
| characters, |
| charactersExcludingSpaces, |
| words, |
| lines |
| }; |
| |
| enum class TextRangeMode : uint8_t |
| { |
| add, |
| subtract, |
| multiply, |
| min, |
| max, |
| difference |
| }; |
| |
| enum class TextRangeType : uint8_t |
| { |
| percentage, |
| unitIndex |
| }; |
| |
| enum class TextRangeInterpolator : uint8_t |
| { |
| linear, |
| cubic |
| }; |
| |
| class GlyphLookup; |
| class TextValueRun; |
| class RangeMapper |
| { |
| public: |
| uint32_t unitCount() { return (uint32_t)m_unitLengths.size(); } |
| uint32_t unitCharacterIndexCount() { return (uint32_t)m_unitCharacterIndices.size(); } |
| |
| void clear(); |
| bool empty() { return m_unitLengths.empty(); } |
| |
| /// Compute ranges of words. |
| void fromWords(Span<const Unichar> text, uint32_t start, uint32_t end); |
| |
| /// Compute ranges of characters in text. |
| void fromCharacters(Span<const Unichar> text, |
| uint32_t start, |
| uint32_t end, |
| const GlyphLookup& glyphLookup, |
| bool withoutSpaces = false); |
| |
| /// Compute ranges of lines. |
| void fromLines(Span<const Unichar> text, |
| uint32_t start, |
| uint32_t end, |
| const SimpleArray<Paragraph>& shape, |
| const SimpleArray<SimpleArray<GlyphLine>>& lines, |
| const GlyphLookup& glyphLookup); |
| |
| float unitToCharacterRange(float word) const; |
| |
| uint32_t unitCharacterIndex(uint32_t at) const |
| { |
| assert(at < m_unitCharacterIndices.size()); |
| return m_unitCharacterIndices[at]; |
| } |
| |
| uint32_t unitLength(uint32_t at) const |
| { |
| assert(at < m_unitLengths.size()); |
| return m_unitLengths[at]; |
| } |
| |
| // Add (some of) unit at indexFrom to indexTo where it falls within the start/end offset. |
| void addRange(uint32_t indexFrom, uint32_t indexTo, uint32_t startOffset, uint32_t endOffset); |
| |
| private: |
| /// Each item in this list represents the index (in unicode codepoints) of |
| /// the selectable element. Always has length 1+unitLengths.length as it's |
| /// expected to always include the final index with 0 length. |
| std::vector<uint32_t> m_unitCharacterIndices; |
| |
| /// Each item in this list represents the length of the matching element at |
| /// the same index in the _unitIndices list. |
| std::vector<uint32_t> m_unitLengths; |
| }; |
| |
| class CubicInterpolatorComponent; |
| class TextModifierRange : public TextModifierRangeBase |
| { |
| public: |
| StatusCode onAddedDirty(CoreContext* context) override; |
| |
| void clearRangeMap(); |
| void computeRange(Span<const Unichar> text, |
| const SimpleArray<Paragraph>& shape, |
| const SimpleArray<SimpleArray<GlyphLine>>& lines, |
| const GlyphLookup& glyphLookup); |
| void computeCoverage(Span<float> coverage); |
| |
| TextRangeUnits units() const { return (TextRangeUnits)unitsValue(); } |
| TextRangeType type() const { return (TextRangeType)typeValue(); } |
| TextRangeMode mode() const { return (TextRangeMode)modeValue(); } |
| void addChild(Component* component) override; |
| bool needsShape() const; |
| |
| #ifdef TESTING |
| CubicInterpolatorComponent* interpolator() const { return m_interpolator; } |
| #endif |
| |
| protected: |
| void modifyFromChanged() override; |
| void modifyToChanged() override; |
| void strengthChanged() override; |
| void unitsValueChanged() override; |
| void typeValueChanged() override; |
| void modeValueChanged() override; |
| void clampChanged() override; |
| void falloffFromChanged() override; |
| void falloffToChanged() override; |
| void offsetChanged() override; |
| |
| private: |
| RangeMapper m_rangeMapper; |
| // Cache indices. |
| float m_indexFrom = 0.0f; |
| float m_indexTo = 0.0f; |
| float m_indexFalloffFrom = 0.0f; |
| float m_indexFalloffTo = 0.0f; |
| CubicInterpolatorComponent* m_interpolator = nullptr; |
| TextValueRun* m_run = nullptr; |
| |
| float offsetModifyFrom() const { return modifyFrom() + offset(); } |
| float offsetModifyTo() const { return modifyTo() + offset(); } |
| float offsetFalloffFrom() const { return falloffFrom() + offset(); } |
| float offsetFalloffTo() const { return falloffTo() + offset(); } |
| |
| float coverageAt(float t); |
| |
| public: |
| #ifdef TESTING |
| TextValueRun* run() const { return m_run; } |
| #endif |
| }; |
| } // namespace rive |
| |
| #endif |