| #ifndef _RIVE_RAW_TEXT_INPUT_HPP_ |
| #define _RIVE_RAW_TEXT_INPUT_HPP_ |
| |
| #ifdef WITH_RIVE_TEXT |
| #include "rive/text/cursor.hpp" |
| #include "rive/text/text.hpp" |
| #include "rive/text/fully_shaped_text.hpp" |
| #include "rive/text/text_selection_path.hpp" |
| |
| namespace rive |
| { |
| class Factory; |
| |
| enum class CursorBoundary : uint8_t |
| { |
| character, |
| word, |
| subWord, |
| line |
| }; |
| |
| class RawTextInput |
| { |
| public: |
| #ifdef TESTING |
| uint32_t measureCount = 0; |
| #endif |
| RawTextInput(); |
| |
| void draw(Factory* factory, |
| Renderer* renderer, |
| const Mat2D& worldTransform, |
| RenderPaint* textPaint, |
| RenderPaint* selectionPaint, |
| RenderPaint* cursorPaint); |
| |
| float fontSize() const { return m_textRun.size; } |
| void fontSize(float value); |
| |
| float maxWidth() const { return m_maxWidth; } |
| void maxWidth(float value); |
| |
| float maxHeight() const { return m_maxHeight; } |
| void maxHeight(float value); |
| |
| TextSizing sizing() const { return m_sizing; } |
| void sizing(TextSizing value); |
| |
| TextOverflow overflow() const { return m_overflow; } |
| void overflow(TextOverflow value); |
| |
| rcp<Font> font() const { return m_textRun.font; } |
| void font(rcp<Font> value); |
| |
| float paragraphSpacing() const { return m_paragraphSpacing; } |
| void paragraphSpacing(float value); |
| |
| float selectionCornerRadius() const { return m_selectionCornerRadius; } |
| void selectionCornerRadius(float value); |
| |
| bool separateSelectionText() const; |
| void separateSelectionText(bool value); |
| |
| enum class Flags : uint8_t |
| { |
| none = 0, |
| shapeDirty = 1 << 0, |
| selectionDirty = 1 << 1, |
| separateSelectionText = 1 << 2, |
| measureDirty = 1 << 3 |
| }; |
| |
| Flags update(Factory* factory); |
| |
| ShapePaintPath* textPath() { return &m_textPath; } |
| ShapePaintPath* selectedTextPath() { return &m_selectedTextPath; } |
| ShapePaintPath* cursorPath() { return &m_cursorPath; } |
| ShapePaintPath* selectionPath() { return &m_selectionPath; } |
| rcp<RenderPath> clipRenderPath() { return m_clipRenderPath; } |
| |
| /// Returns the bounds of the text object (helpful for aligning multiple |
| /// text objects/procredurally drawn shapes). |
| AABB bounds() const; |
| CursorVisualPosition cursorVisualPosition(CursorPosition position) |
| { |
| return position.visualPosition(m_shape); |
| } |
| |
| CursorVisualPosition cursorVisualPosition() const |
| { |
| return m_cursorVisualPosition; |
| } |
| |
| void insert(const std::string& text); |
| void insert(Unichar codePoint); |
| void erase(); |
| void backspace(int32_t direction); |
| |
| void cursorLeft(CursorBoundary boundary = CursorBoundary::character, |
| bool select = false); |
| void cursorRight(CursorBoundary boundary = CursorBoundary::character, |
| bool select = false); |
| void cursorUp(bool select = false); |
| void cursorDown(bool select = false); |
| |
| void moveCursorTo(Vec2D translation, bool select = false); |
| const FullyShapedText& shape() const { return m_shape; } |
| const Cursor cursor() const { return m_cursor; } |
| void cursor(Cursor value); |
| |
| // Selects the word at the cursor. |
| void selectWord(); |
| |
| std::string text() const; |
| void text(std::string value); |
| // Length of the input text. |
| size_t length() const; |
| |
| // Returns true if the input is empty. |
| bool empty() const; |
| |
| void undo(); |
| void redo(); |
| |
| AABB measure(float maxWidth, float maxHeight); |
| |
| enum class Delineator : uint8_t |
| { |
| unknown = 0, |
| lowercase = 1 << 0, |
| uppercase = 1 << 1, |
| symbol = 1 << 2, |
| underscore = 1 << 3, |
| whitespace = 1 << 4, |
| word = lowercase | uppercase | underscore, |
| any = |
| lowercase | uppercase | symbol | underscore | whitespace | lowercase |
| |
| }; |
| |
| private: |
| void captureJournalEntry(Cursor cursor); |
| void cursorHorizontal(int32_t offset, CursorBoundary boundary, bool select); |
| static Delineator classify(Unichar codepoint); |
| Delineator classify(CursorPosition position) const; |
| |
| // Hunt for a delineator bit maks from position in direction. Returns what |
| // was actually found. The position will be updated to the location where |
| // the Delineator was found. |
| Delineator find(uint8_t delineatorMask, |
| CursorPosition& position, |
| int32_t direction) const; |
| |
| CursorPosition findPosition(uint8_t delineatorMask, |
| const CursorPosition& position, |
| int32_t direction) const; |
| |
| const OrderedLine* orderedLine(CursorPosition position) const; |
| |
| void buildTextPaths(Factory* factory); |
| void computeVisualPositionFromCursor(); |
| void setTextPrivate(std::string value); |
| bool flagged(Flags mask) const; |
| bool unflag(Flags mask); |
| void flag(Flags mask); |
| |
| Cursor m_cursor; |
| TextRun m_textRun; |
| ShapePaintPath m_textPath; |
| ShapePaintPath m_selectedTextPath; |
| ShapePaintPath m_cursorPath; |
| TextSelectionPath m_selectionPath; |
| std::vector<Unichar> m_text; |
| |
| FullyShapedText m_shape; |
| std::unique_ptr<FullyShapedText> m_measuringShape; |
| float m_lastMeasureMaxWidth = 0.0f; |
| float m_lastMeasureMaxHeight = 0.0f; |
| |
| Flags m_flags = Flags::none; |
| |
| float m_paragraphSpacing = 0.0f; |
| TextOrigin m_origin = TextOrigin::top; |
| TextSizing m_sizing = TextSizing::autoWidth; |
| TextOverflow m_overflow = TextOverflow::visible; |
| TextAlign m_align = TextAlign::left; |
| TextWrap m_wrap = TextWrap::wrap; |
| float m_maxWidth = 0.0f; |
| float m_maxHeight = 0.0f; |
| rcp<RenderPath> m_clipRenderPath; |
| float m_idealCursorX = -1.0f; |
| |
| CursorVisualPosition m_cursorVisualPosition; |
| std::vector<AABB> m_selectionRects; |
| |
| float m_selectionCornerRadius = 5.0f; |
| |
| struct JournalEntry |
| { |
| Cursor cursorFrom; |
| Cursor cursorTo; |
| std::string text; |
| }; |
| std::vector<JournalEntry> m_journal; |
| uint32_t m_journalIndex = 0; |
| }; |
| |
| // Helper for performing bitwise and with Delineator. |
| inline uint8_t operator&(const RawTextInput::Delineator& delineator, |
| const uint8_t mask) |
| { |
| return (uint8_t)delineator & mask; |
| } |
| |
| inline uint8_t operator~(const RawTextInput::Delineator& delineator) |
| { |
| return ~(uint8_t)delineator; |
| } |
| |
| inline RawTextInput::Delineator operator|(const RawTextInput::Delineator& a, |
| const RawTextInput::Delineator& b) |
| { |
| return (RawTextInput::Delineator)((uint8_t)a | (uint8_t)b); |
| } |
| |
| inline RawTextInput::Delineator operator&(const RawTextInput::Delineator& a, |
| const RawTextInput::Delineator& b) |
| { |
| return (RawTextInput::Delineator)((uint8_t)a & (uint8_t)b); |
| } |
| RIVE_MAKE_ENUM_BITSET(RawTextInput::Flags); |
| } // namespace rive |
| |
| #endif |
| #endif |