Treat measured nodes size as a minimun contraint when rounding

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
This commit is contained in:
Emil Sjolander
2017-04-30 03:03:43 -07:00
committed by Facebook Github Bot
parent 7b89a1dd48
commit 40e1bf6ce3
2 changed files with 28 additions and 13 deletions

View File

@@ -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);

View File

@@ -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) {
@@ -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++) {