Skip to content

Commit

Permalink
Treat measured nodes size as a minimun contraint when rounding
Browse files Browse the repository at this point in the history
Summary: We need to treat measurements from nodes with measure functions as minimum values as to not truncate text.

Reviewed By: shergin

Differential Revision: D4972290

fbshipit-source-id: 0a7bcc7f47b3e5acb8745da5286abcb9c4e44a38
  • Loading branch information
Emil Sjolander authored and facebook-github-bot committed Apr 30, 2017
1 parent 7b89a1d commit 40e1bf6
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
14 changes: 7 additions & 7 deletions tests/YGRoundingMeasureFuncTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,29 +49,29 @@ TEST(YogaTest, rounding_feature_with_custom_measure_func_floor) {

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(11, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(11, YGNodeLayoutGetHeight(root_child0));

YGConfigSetPointScaleFactor(config, 2.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);

ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(10.5, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10.5, YGNodeLayoutGetHeight(root_child0));

YGConfigSetPointScaleFactor(config, 4.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

ASSERT_FLOAT_EQ(10.25f, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10.25, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10.25, YGNodeLayoutGetHeight(root_child0));

YGConfigSetPointScaleFactor(config, 1.0f / 3.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);

ASSERT_FLOAT_EQ(9.0, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(9.0, YGNodeLayoutGetHeight(root_child0));
ASSERT_FLOAT_EQ(12.0, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(12.0, YGNodeLayoutGetHeight(root_child0));

YGNodeFreeRecursive(root);

Expand Down
27 changes: 21 additions & 6 deletions yoga/Yoga.c
Original file line number Diff line number Diff line change
Expand Up @@ -3297,9 +3297,20 @@ void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInP
}
}

static float YGRoundValueToPixelGrid(const float value, const float pointScaleFactor) {
static float YGRoundValueToPixelGrid(const float value, const float pointScaleFactor, const bool forceCeil, const bool forceFloor) {
float fractial = fmodf(value, pointScaleFactor);
return value - fractial + (fractial >= pointScaleFactor / 2.0f ? pointScaleFactor : 0);
if (YGFloatsEqual(fractial, 0)) {
// Still remove fractial as fractial could be extremely small.
return value - fractial;
}

if (forceCeil) {
return value - fractial + pointScaleFactor;
} else if (forceFloor) {
return value - fractial;
} else {
return value - fractial + (fractial >= pointScaleFactor / 2.0f ? pointScaleFactor : 0);
}
}

static void YGRoundToPixelGrid(const YGNodeRef node, const float pointScaleFactor, const float absoluteLeft, const float absoluteTop) {
Expand All @@ -3319,13 +3330,17 @@ static void YGRoundToPixelGrid(const YGNodeRef node, const float pointScaleFacto
const float absoluteNodeRight = absoluteNodeLeft + nodeWidth;
const float absoluteNodeBottom = absoluteNodeTop + nodeHeight;

node->layout.position[YGEdgeLeft] = YGRoundValueToPixelGrid(nodeLeft, pointScaleFactor);
node->layout.position[YGEdgeTop] = YGRoundValueToPixelGrid(nodeTop, pointScaleFactor);
// If a node has a custom measure function we never want to round down its size as this could
// lead to unwanted text truncation.
const bool hasMeasure = node->measure != NULL;

node->layout.position[YGEdgeLeft] = YGRoundValueToPixelGrid(nodeLeft, pointScaleFactor, false, hasMeasure);
node->layout.position[YGEdgeTop] = YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, hasMeasure);

node->layout.dimensions[YGDimensionWidth] =
YGRoundValueToPixelGrid(absoluteNodeRight, pointScaleFactor) - YGRoundValueToPixelGrid(absoluteNodeLeft, pointScaleFactor);
YGRoundValueToPixelGrid(absoluteNodeRight, pointScaleFactor, hasMeasure, false) - YGRoundValueToPixelGrid(absoluteNodeLeft, pointScaleFactor, false, hasMeasure);
node->layout.dimensions[YGDimensionHeight] =
YGRoundValueToPixelGrid(absoluteNodeBottom, pointScaleFactor) - YGRoundValueToPixelGrid(absoluteNodeTop, pointScaleFactor);
YGRoundValueToPixelGrid(absoluteNodeBottom, pointScaleFactor, hasMeasure, false) - YGRoundValueToPixelGrid(absoluteNodeTop, pointScaleFactor, false, hasMeasure);

const uint32_t childCount = YGNodeListCount(node->children);
for (uint32_t i = 0; i < childCount; i++) {
Expand Down

0 comments on commit 40e1bf6

Please sign in to comment.