Skip to content

Commit

Permalink
Simple procedural text rendering API
Browse files Browse the repository at this point in the history
This adds `rive::RawText` can be used to append text runs with different styles and set layout rules for the text. It's pretty full featured.

Simple example (trimmed for brevity):
```
auto roboto = loadFont("RobotoFlex.ttf");

// setup text object
rive::RawText text(RiveFactory());
text.append("Hello world! ", roboto);

// later during rendering
text.render(renderer);
```

<img width="538" alt="CleanShot 2024-07-25 at 21 59 43@2x" src="https://github.com/user-attachments/assets/7c421cca-ec91-4978-b358-7ba5d457746a">

A few more complex examples:
```
auto roboto = loadFont("RobotoFlex.ttf");
auto montserrat = loadFont("Montserrat.ttf");

rive::RawText text(RiveFactory());
text.append("Hello world! ", roboto, 72.0f);
text.append("Moon's cool too. ", montserrat, 64.0f);
```
<img width="491" alt="CleanShot 2024-07-25 at 22 01 28@2x" src="https://github.com/user-attachments/assets/06272869-11dc-43f3-a7a3-6bde7a226238">

Because `RawText` represents one contiguous styled block of text, you can apply rules like overflow, sizing, alignment, different paint, etc:

```
rive::RawText text(RiveFactory());
text.maxWidth(450.0f);
text.maxHeight(330.0f);
text.sizing(rive::TextSizing::fixed);
text.overflow(rive::TextOverflow::ellipsis);
text.append("Hello world! ", roboto, 72.0f);
text.append("Moon's cool too. ", montserrat, 64.0f);

auto paint = RiveFactory()->makeRenderPaint();
paint->color(0x88ff0000);
text.append("Mars is red.", roboto, 72.0f, paint);
```
<img width="401" alt="CleanShot 2024-07-25 at 22 03 01@2x" src="https://github.com/user-attachments/assets/bf03d1e6-c966-4834-92ab-20d9918186ad">

You can also supply an override paint during rendering to force paint the whole thing with one color:
```
auto paint = RiveFactory()->makeRenderPaint();
paint->color(0xff00ff00);
text.render(renderer, paint);
```
<img width="321" alt="CleanShot 2024-07-25 at 22 04 44@2x" src="https://github.com/user-attachments/assets/eaaf2983-4cd5-45e0-96fd-5edc72da211a">

Diffs=
a56419984 Simple procedural text rendering API (#7701)

Co-authored-by: Chris Dalton <[email protected]>
Co-authored-by: Luigi Rosso <[email protected]>
  • Loading branch information
3 people committed Jul 26, 2024
1 parent 1510178 commit 7b2347c
Show file tree
Hide file tree
Showing 6 changed files with 452 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d6d79132b5c6aa46c1919918a14de28f1cbf93a4
a56419984ccdd39989f7c059a8af2ebbceb379a0
96 changes: 96 additions & 0 deletions include/rive/text/raw_text.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#ifndef _RIVE_RENDER_TEXT_HPP_
#define _RIVE_RENDER_TEXT_HPP_

#ifdef WITH_RIVE_TEXT

#include "rive/text/text.hpp"

namespace rive
{
class Factory;

class RawText
{
public:
RawText(Factory* factory);

/// Returns true if the text object contains no text.
bool empty() const;

/// Appends a run to the text object.
void append(const std::string& text,
rcp<RenderPaint> paint,
rcp<Font> font,
float size = 16.0f,
float lineHeight = -1.0f,
float letterSpacing = 0.0f);

/// Resets the text object to empty state (no text).
void clear();

/// Draw the text using renderer. Second argument is optional to override
/// all paints provided with run styles
void render(Renderer* renderer, rcp<RenderPaint> paint = nullptr);

TextSizing sizing() const;
TextOverflow overflow() const;
TextAlign align() const;
float maxWidth() const;
float maxHeight() const;
float paragraphSpacing() const;

void sizing(TextSizing value);

/// How text that overflows when TextSizing::fixed is used.
void overflow(TextOverflow value);

/// How text aligns within the bounds.
void align(TextAlign value);

/// The width at which the text will wrap when using any sizing but TextSizing::auto.
void maxWidth(float value);

/// The height at which the text will overflow when using TextSizing::fixed.
void maxHeight(float value);

/// The vertical space between paragraphs delineated by a return character.
void paragraphSpacing(float value);

/// Returns the bounds of the text object (helpful for aligning multiple
/// text objects/procredurally drawn shapes).
AABB bounds();

private:
void update();
struct RenderStyle
{
rcp<RenderPaint> paint;
rcp<RenderPath> path;
bool isEmpty;
};
SimpleArray<Paragraph> m_shape;
SimpleArray<SimpleArray<GlyphLine>> m_lines;

StyledText m_styled;
Factory* m_factory;
std::vector<RenderStyle> m_styles;
std::vector<RenderStyle*> m_renderStyles;
bool m_dirty = false;
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;
float m_maxWidth = 0.0f;
float m_maxHeight = 0.0f;
std::vector<OrderedLine> m_orderedLines;
GlyphRun m_ellipsisRun;
AABB m_bounds;
rcp<RenderPath> m_clipRenderPath;
};
} // namespace rive

#endif // WITH_RIVE_TEXT

#endif
3 changes: 3 additions & 0 deletions include/rive/text/text.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ class Text : public TextBase
float effectiveHeight() { return std::isnan(m_layoutHeight) ? height() : m_layoutHeight; }
#ifdef WITH_RIVE_TEXT
const std::vector<TextValueRun*>& runs() const { return m_runs; }
static SimpleArray<SimpleArray<GlyphLine>> BreakLines(const SimpleArray<Paragraph>& paragraphs,
float width,
TextAlign align);
#endif

bool haveModifiers() const
Expand Down
1 change: 1 addition & 0 deletions src/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "rive/factory.hpp"
#include "rive/math/aabb.hpp"
#include "rive/math/raw_path.hpp"
#include "rive/text/raw_text.hpp"
#ifdef WITH_RIVE_TEXT
#include "rive/text/font_hb.hpp"
#endif
Expand Down
Loading

0 comments on commit 7b2347c

Please sign in to comment.