Skip to content

Commit

Permalink
8020 text fit to box
Browse files Browse the repository at this point in the history
Adds support, behind a feature flag, for fitting and non wrapped text

Diffs=
39b803c58 8020 text fit to box (#8042)

Co-authored-by: hernan <[email protected]>
  • Loading branch information
bodymovin and bodymovin committed Sep 3, 2024
1 parent dc59953 commit f07269d
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b06e05dc18248d218807e00779d35c94bdfb8efe
39b803c5886b7df76471e58e8584744b86296c17
9 changes: 9 additions & 0 deletions dev/defs/text/text.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@
"string": "originValue"
},
"description": "Logical starting location of origin."
},
"wrapValue": {
"type": "uint",
"initialValue": "0",
"key": {
"int": 683,
"string": "wrapvalue"
},
"description": "One of wrap, noWrap"
}
}
}
8 changes: 8 additions & 0 deletions include/rive/generated/core_registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,9 @@ class CoreRegistry
case TextBase::originValuePropertyKey:
object->as<TextBase>()->originValue(value);
break;
case TextBase::wrapValuePropertyKey:
object->as<TextBase>()->wrapValue(value);
break;
case TextValueRunBase::styleIdPropertyKey:
object->as<TextValueRunBase>()->styleId(value);
break;
Expand Down Expand Up @@ -2155,6 +2158,8 @@ class CoreRegistry
return object->as<TextBase>()->overflowValue();
case TextBase::originValuePropertyKey:
return object->as<TextBase>()->originValue();
case TextBase::wrapValuePropertyKey:
return object->as<TextBase>()->wrapValue();
case TextValueRunBase::styleIdPropertyKey:
return object->as<TextValueRunBase>()->styleId();
case FileAssetBase::assetIdPropertyKey:
Expand Down Expand Up @@ -2772,6 +2777,7 @@ class CoreRegistry
case TextBase::sizingValuePropertyKey:
case TextBase::overflowValuePropertyKey:
case TextBase::originValuePropertyKey:
case TextBase::wrapValuePropertyKey:
case TextValueRunBase::styleIdPropertyKey:
case FileAssetBase::assetIdPropertyKey:
case AudioEventBase::assetIdPropertyKey:
Expand Down Expand Up @@ -3387,6 +3393,8 @@ class CoreRegistry
return object->is<TextBase>();
case TextBase::originValuePropertyKey:
return object->is<TextBase>();
case TextBase::wrapValuePropertyKey:
return object->is<TextBase>();
case TextValueRunBase::styleIdPropertyKey:
return object->is<TextValueRunBase>();
case FileAssetBase::assetIdPropertyKey:
Expand Down
18 changes: 18 additions & 0 deletions include/rive/generated/text/text_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class TextBase : public Drawable
static const uint16_t originYPropertyKey = 367;
static const uint16_t paragraphSpacingPropertyKey = 371;
static const uint16_t originValuePropertyKey = 377;
static const uint16_t wrapValuePropertyKey = 683;

private:
uint32_t m_AlignValue = 0;
Expand All @@ -54,6 +55,7 @@ class TextBase : public Drawable
float m_OriginY = 0.0f;
float m_ParagraphSpacing = 0.0f;
uint32_t m_OriginValue = 0;
uint32_t m_WrapValue = 0;

public:
inline uint32_t alignValue() const { return m_AlignValue; }
Expand Down Expand Up @@ -155,6 +157,17 @@ class TextBase : public Drawable
originValueChanged();
}

inline uint32_t wrapValue() const { return m_WrapValue; }
void wrapValue(uint32_t value)
{
if (m_WrapValue == value)
{
return;
}
m_WrapValue = value;
wrapValueChanged();
}

Core* clone() const override;
void copy(const TextBase& object)
{
Expand All @@ -167,6 +180,7 @@ class TextBase : public Drawable
m_OriginY = object.m_OriginY;
m_ParagraphSpacing = object.m_ParagraphSpacing;
m_OriginValue = object.m_OriginValue;
m_WrapValue = object.m_WrapValue;
Drawable::copy(object);
}

Expand Down Expand Up @@ -201,6 +215,9 @@ class TextBase : public Drawable
case originValuePropertyKey:
m_OriginValue = CoreUintType::deserialize(reader);
return true;
case wrapValuePropertyKey:
m_WrapValue = CoreUintType::deserialize(reader);
return true;
}
return Drawable::deserialize(propertyKey, reader);
}
Expand All @@ -215,6 +232,7 @@ class TextBase : public Drawable
virtual void originYChanged() {}
virtual void paragraphSpacingChanged() {}
virtual void originValueChanged() {}
virtual void wrapValueChanged() {}
};
} // namespace rive

Expand Down
11 changes: 10 additions & 1 deletion include/rive/text/text.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ enum class TextOverflow : uint8_t
visible,
hidden,
clipped,
ellipsis
ellipsis,
fit,
};

enum class TextOrigin : uint8_t
Expand All @@ -31,6 +32,12 @@ enum class TextOrigin : uint8_t
baseline
};

enum class TextWrap : uint8_t
{
wrap,
noWrap
};

class OrderedLine;
class TextModifierGroup;

Expand Down Expand Up @@ -175,6 +182,7 @@ class Text : public TextBase
void modifierShapeDirty();
void markPaintDirty();
void update(ComponentDirt value) override;
Mat2D m_fitScale;

TextSizing sizing() const { return (TextSizing)sizingValue(); }
TextSizing effectiveSizing() const
Expand All @@ -183,6 +191,7 @@ class Text : public TextBase
}
TextOverflow overflow() const { return (TextOverflow)overflowValue(); }
TextOrigin textOrigin() const { return (TextOrigin)originValue(); }
TextWrap wrap() const { return (TextWrap)wrapValue(); }
void overflow(TextOverflow value) { return overflowValue((uint32_t)value); }
void buildRenderStyles();
const TextStyle* styleFromShaperId(uint16_t id) const;
Expand Down
67 changes: 52 additions & 15 deletions src/text/text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,38 @@ void Text::buildRenderStyles()
}
y += paragraphSpace;
}
if (overflow() == TextOverflow::fit)
{
auto xScale = (effectiveSizing() != TextSizing::autoWidth && maxWidth > m_bounds.width())
? m_bounds.width() / maxWidth
: 1;
auto baseline = m_lines[0][0].baseline;
auto yScale = (effectiveSizing() == TextSizing::fixed && y > m_bounds.height())
? (m_bounds.height() - baseline) / (y - baseline)
: 1;
if (xScale != 1 || yScale != 1)
{
auto scale = std::max(0.0f, xScale > yScale ? yScale : xScale);
auto yOffset = baseline * (1 - scale);
auto xOffset = 0.0f;
switch ((TextAlign)alignValue())
{
case TextAlign::center:
xOffset = (m_bounds.width() - maxWidth * scale) / 2;
break;
case TextAlign::right:
xOffset = (m_bounds.width() - maxWidth * scale);
break;
default:
break;
}
m_fitScale = Mat2D::fromScaleAndTranslation(scale, scale, xOffset, yOffset);
}
else
{
m_fitScale = Mat2D();
}
}
}

const TextStyle* Text::styleFromShaperId(uint16_t id) const
Expand All @@ -517,7 +549,7 @@ void Text::draw(Renderer* renderer)
}
if (clipResult != ClipResult::emptyClip)
{
renderer->transform(m_WorldTransform);
renderer->transform(m_WorldTransform * m_fitScale);
if (overflow() == TextOverflow::clipped && m_clipRenderPath)
{
renderer->clipPath(m_clipRenderPath.get());
Expand Down Expand Up @@ -704,10 +736,12 @@ void Text::update(ComponentDirt value)
makeStyled(m_modifierStyledText, false);
auto runs = m_modifierStyledText.runs();
m_modifierShape = runs[0].font->shapeText(m_modifierStyledText.unichars(), runs);
m_modifierLines =
BreakLines(m_modifierShape,
effectiveSizing() == TextSizing::autoWidth ? -1.0f : effectiveWidth(),
(TextAlign)alignValue());
m_modifierLines = BreakLines(
m_modifierShape,
(effectiveSizing() == TextSizing::autoWidth || wrap() == TextWrap::noWrap)
? -1.0f
: effectiveWidth(),
(TextAlign)alignValue());
m_glyphLookup.compute(m_modifierStyledText.unichars(), m_modifierShape);
uint32_t textSize = (uint32_t)m_modifierStyledText.unichars().size();
for (TextModifierGroup* group : m_modifierGroups)
Expand All @@ -723,10 +757,12 @@ void Text::update(ComponentDirt value)
{
auto runs = m_styledText.runs();
m_shape = runs[0].font->shapeText(m_styledText.unichars(), runs);
m_lines =
BreakLines(m_shape,
effectiveSizing() == TextSizing::autoWidth ? -1.0f : effectiveWidth(),
(TextAlign)alignValue());
m_lines = BreakLines(
m_shape,
(effectiveSizing() == TextSizing::autoWidth || wrap() == TextWrap::noWrap)
? -1.0f
: effectiveWidth(),
(TextAlign)alignValue());
if (!precomputeModifierCoverage && haveModifiers())
{
m_glyphLookup.compute(m_styledText.unichars(), m_shape);
Expand Down Expand Up @@ -775,12 +811,13 @@ Vec2D Text::measure(Vec2D maxSize)
const float paragraphSpace = paragraphSpacing();
auto runs = m_styledText.runs();
auto shape = runs[0].font->shapeText(m_styledText.unichars(), runs);
auto lines = BreakLines(shape,
std::min(maxSize.x,
sizing() == TextSizing::autoWidth
? std::numeric_limits<float>::max()
: width()),
(TextAlign)alignValue());
auto lines =
BreakLines(shape,
std::min(maxSize.x,
(sizing() == TextSizing::autoWidth || wrap() == TextWrap::noWrap)
? std::numeric_limits<float>::max()
: width()),
(TextAlign)alignValue());
float y = 0;
float computedHeight = 0.0f;
float minY = 0;
Expand Down

0 comments on commit f07269d

Please sign in to comment.