Skip to content

Commit

Permalink
Fix Yoga crash with percent margin
Browse files Browse the repository at this point in the history
When a layout is set to use percent margins at the same time that that layout node can't be computed due to a combination of hug/fill layouts, Yoga asserts with:

"availableWidth is indefinite so widthMeasureMode must be YGMeasureModeUndefined"
or
"availableHeight is indefinite so heightMeasureMode must be YGMeasureModeUndefined"

This crash only occurs with percent margins, not padding. At this point its unclear whether this is a bug in Yoga but this PR mitigates the crash.

Diffs=
339867b4de Fix Yoga crash with percent margin (#9010)

Co-authored-by: Philip Chung <[email protected]>
  • Loading branch information
philter and philter committed Feb 11, 2025
1 parent e21572f commit dc3000b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7968fd06b819e702e1a6fea94221e93e356c889a
339867b4de68e3c301409dad079747b954d4fa11
2 changes: 2 additions & 0 deletions include/rive/layout_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ class LayoutComponent : public LayoutComponentBase,
void scaleTypeChanged();
void displayChanged();
void flexDirectionChanged();
bool willComputeValidWidth();
bool willComputeValidHeight();
#endif
void buildDependencies() override;

Expand Down
79 changes: 74 additions & 5 deletions src/layout_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,57 @@ StatusCode LayoutComponent::onAddedClean(CoreContext* context)
return StatusCode::Ok;
}

bool LayoutComponent::willComputeValidWidth()
{
auto p = parent();
while (p != nullptr)
{
if (p->is<LayoutComponent>() && !p->is<Artboard>())
{
auto layout = p->as<LayoutComponent>();
if (layout->style() != nullptr)
{
if (layout->style()->widthScaleType() == LayoutScaleType::fixed)
{
return true;
}
if (layout->style()->positionType() == YGPositionTypeAbsolute)
{
break;
}
}
}
p = p->parent();
}
return false;
}

bool LayoutComponent::willComputeValidHeight()
{
auto p = parent();
while (p != nullptr)
{
if (p->is<LayoutComponent>() && !p->is<Artboard>())
{
auto layout = p->as<LayoutComponent>();
if (layout->style() != nullptr)
{
if (layout->style()->heightScaleType() ==
LayoutScaleType::fixed)
{
return true;
}
if (layout->style()->positionType() == YGPositionTypeAbsolute)
{
break;
}
}
}
p = p->parent();
}
return false;
}

void LayoutComponent::drawProxy(Renderer* renderer)
{
if (clip())
Expand Down Expand Up @@ -704,14 +755,32 @@ void LayoutComponent::syncStyle()
YGValue{m_style->borderTop(), m_style->borderTopUnits()};
ygStyle.border()[YGEdgeBottom] =
YGValue{m_style->borderBottom(), m_style->borderBottomUnits()};

auto hasValidWidth = willComputeValidWidth();
auto hasValidHeight = willComputeValidHeight();
auto marginLeftUnits =
!hasValidWidth && m_style->marginLeftUnits() == YGUnitPercent
? YGUnitAuto
: m_style->marginLeftUnits();
auto marginRightUnits =
!hasValidWidth && m_style->marginRightUnits() == YGUnitPercent
? YGUnitAuto
: m_style->marginRightUnits();
auto marginTopUnits =
!hasValidHeight && m_style->marginTopUnits() == YGUnitPercent
? YGUnitAuto
: m_style->marginTopUnits();
auto marginBottomUnits =
!hasValidHeight && m_style->marginBottomUnits() == YGUnitPercent
? YGUnitAuto
: m_style->marginBottomUnits();
ygStyle.margin()[YGEdgeLeft] =
YGValue{m_style->marginLeft(), m_style->marginLeftUnits()};
YGValue{m_style->marginLeft(), marginLeftUnits};
ygStyle.margin()[YGEdgeRight] =
YGValue{m_style->marginRight(), m_style->marginRightUnits()};
ygStyle.margin()[YGEdgeTop] =
YGValue{m_style->marginTop(), m_style->marginTopUnits()};
YGValue{m_style->marginRight(), marginRightUnits};
ygStyle.margin()[YGEdgeTop] = YGValue{m_style->marginTop(), marginTopUnits};
ygStyle.margin()[YGEdgeBottom] =
YGValue{m_style->marginBottom(), m_style->marginBottomUnits()};
YGValue{m_style->marginBottom(), marginBottomUnits};
ygStyle.padding()[YGEdgeLeft] =
YGValue{m_style->paddingLeft(), m_style->paddingLeftUnits()};
ygStyle.padding()[YGEdgeRight] =
Expand Down

0 comments on commit dc3000b

Please sign in to comment.