Skip to content

Commit

Permalink
Move pointscalefactor to config
Browse files Browse the repository at this point in the history
Summary:
This adds some improvements to the new ```YGConfig```, it tackles facebook#452 and moves the scalefactor into the config.
Closes facebook#457

Differential Revision: D4675088

Pulled By: emilsjolander

fbshipit-source-id: 99b2c734d6c5139fe1dc8bdeb014bb038f0e337d
  • Loading branch information
woehrl01 authored and facebook-github-bot committed Mar 9, 2017
1 parent 0445962 commit 406c8a2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 37 deletions.
16 changes: 7 additions & 9 deletions tests/YGRoundingMeasureFuncTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,35 @@ TEST(YogaTest, rounding_feature_with_custom_measure_func_floor) {
YGNodeSetMeasureFunc(root_child0, _measureFloor);
YGNodeInsertChild(root, root_child0, 0);

YGSetPointScaleFactor(0.0);
YGConfigSetPointScaleFactor(config, 0.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);

ASSERT_FLOAT_EQ(10.2, YGNodeLayoutGetWidth(root_child0));
ASSERT_FLOAT_EQ(10.2, YGNodeLayoutGetHeight(root_child0));

YGSetPointScaleFactor(1.0);
YGConfigSetPointScaleFactor(config, 1.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

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

YGSetPointScaleFactor(2.0);
YGConfigSetPointScaleFactor(config, 2.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);

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

YGSetPointScaleFactor(4.0);
YGConfigSetPointScaleFactor(config, 4.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

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

YGSetPointScaleFactor(1.0 / 3.0);
YGConfigSetPointScaleFactor(config, 1.0f / 3.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL);

Expand All @@ -77,7 +77,6 @@ TEST(YogaTest, rounding_feature_with_custom_measure_func_floor) {

YGNodeFreeRecursive(root);

YGSetPointScaleFactor(1.0);
YGConfigFree(config);
}

Expand All @@ -91,7 +90,7 @@ TEST(YogaTest, rounding_feature_with_custom_measure_func_ceil) {
YGNodeSetMeasureFunc(root_child0, _measureCeil);
YGNodeInsertChild(root, root_child0, 0);

YGSetPointScaleFactor(1.0);
YGConfigSetPointScaleFactor(config, 1.0f);

YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);

Expand All @@ -100,6 +99,5 @@ TEST(YogaTest, rounding_feature_with_custom_measure_func_ceil) {

YGNodeFreeRecursive(root);

YGSetPointScaleFactor(1.0);
YGConfigFree(config);
}
51 changes: 25 additions & 26 deletions yoga/Yoga.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef struct YGStyle {
typedef struct YGConfig {
bool experimentalFeatures[YGExperimentalFeatureCount + 1];
bool useWebDefaults;
float pointScaleFactor;
} YGConfig;

typedef struct YGNode {
Expand Down Expand Up @@ -206,6 +207,7 @@ static YGConfig gYGConfigDefaults = {
[YGExperimentalFeatureWebFlexBasis] = false,
},
.useWebDefaults = false,
.pointScaleFactor = 1.0f
};

static void YGNodeMarkDirtyInternal(const YGNodeRef node);
Expand Down Expand Up @@ -307,7 +309,6 @@ static inline float YGValueResolveMargin(const YGValue *const value, const float

int32_t gNodeInstanceCount = 0;


WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
const YGNodeRef node = gYGMalloc(sizeof(YGNode));
YG_ASSERT(node, "Could not allocate memory for node");
Expand Down Expand Up @@ -1404,7 +1405,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,

if (!YGFloatIsUndefined(resolvedFlexBasis) && !YGFloatIsUndefined(mainAxisSize)) {
if (YGFloatIsUndefined(child->layout.computedFlexBasis) ||
(YGConfigIsExperimentalFeatureEnabled(config, YGExperimentalFeatureWebFlexBasis) &&
(YGConfigIsExperimentalFeatureEnabled(child->config, YGExperimentalFeatureWebFlexBasis) &&
child->layout.computedFlexBasisGeneration != gCurrentGenerationCount)) {
child->layout.computedFlexBasis =
fmaxf(resolvedFlexBasis, YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth));
Expand Down Expand Up @@ -2231,7 +2232,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
availableInnerMainDim = minInnerMainDim;
} else if (!YGFloatIsUndefined(maxInnerMainDim) && sizeConsumedOnCurrentLine > maxInnerMainDim) {
availableInnerMainDim = maxInnerMainDim;
} else if (YGConfigIsExperimentalFeatureEnabled(config, YGExperimentalFeatureMinFlexFix)) {
} else if (YGConfigIsExperimentalFeatureEnabled(node->config, YGExperimentalFeatureMinFlexFix)) {
// TODO: this needs to be moved out of experimental feature, as this is legitimate fix
// If the measurement isn't exact, we want to use as little space as possible
availableInnerMainDim = sizeConsumedOnCurrentLine;
Expand Down Expand Up @@ -3312,62 +3313,60 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
return (needToVisitNode || cachedResults == NULL);
}

static float gPointScaleFactor = 1.0;

void YGSetPointScaleFactor(float pixelsInPoint) {
void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint) {
YG_ASSERT(pixelsInPoint >= 0.0f, "Scale factor should not be less than zero");
// We store points for Pixel as we will use it for rounding
if (pixelsInPoint == 0.0f) {
// Zero is used to skip rounding
gPointScaleFactor = 0.0f;
config->pointScaleFactor = 0.0f;
} else {
gPointScaleFactor = 1.0f / pixelsInPoint;
config->pointScaleFactor = 1.0f / pixelsInPoint;
}
}

static void YGRoundToPixelGrid(const YGNodeRef node) {
if (gPointScaleFactor == 0.0f) {
static void YGRoundToPixelGrid(const YGNodeRef node, const float pointScaleFactor) {
if (pointScaleFactor == 0.0f) {
return;
}
const float nodeLeft = node->layout.position[YGEdgeLeft];
const float nodeTop = node->layout.position[YGEdgeTop];

// To round correctly to the pixel grid, first we calculate left and top coordinates
float fractialLeft = fmodf(nodeLeft, gPointScaleFactor);
float fractialTop = fmodf(nodeTop, gPointScaleFactor);
float fractialLeft = fmodf(nodeLeft, pointScaleFactor);
float fractialTop = fmodf(nodeTop, pointScaleFactor);
float roundedLeft = nodeLeft - fractialLeft;
float roundedTop = nodeTop - fractialTop;

// To do the actual rounding we check if leftover fraction is bigger or equal than half of the grid step
if (fractialLeft >= gPointScaleFactor / 2.0) {
roundedLeft += gPointScaleFactor;
fractialLeft -= gPointScaleFactor;
if (fractialLeft >= pointScaleFactor / 2.0f) {
roundedLeft += pointScaleFactor;
fractialLeft -= pointScaleFactor;
}
if (fractialTop >= gPointScaleFactor / 2.0) {
roundedTop += gPointScaleFactor;
fractialTop -= gPointScaleFactor;
if (fractialTop >= pointScaleFactor / 2.0f) {
roundedTop += pointScaleFactor;
fractialTop -= pointScaleFactor;
}
node->layout.position[YGEdgeLeft] = roundedLeft;
node->layout.position[YGEdgeTop] = roundedTop;

// Now we round width and height in the same way accounting for fractial leftovers from rounding position
const float adjustedWidth = fractialLeft + node->layout.dimensions[YGDimensionWidth];
const float adjustedHeight = fractialTop + node->layout.dimensions[YGDimensionHeight];
float roundedWidth = adjustedWidth - fmodf(adjustedWidth, gPointScaleFactor);
float roundedHeight = adjustedHeight - fmodf(adjustedHeight, gPointScaleFactor);
float roundedWidth = adjustedWidth - fmodf(adjustedWidth, pointScaleFactor);
float roundedHeight = adjustedHeight - fmodf(adjustedHeight, pointScaleFactor);

if (adjustedWidth - roundedWidth >= gPointScaleFactor / 2.0) {
roundedWidth += gPointScaleFactor;
if (adjustedWidth - roundedWidth >= pointScaleFactor / 2.0f) {
roundedWidth += pointScaleFactor;
}
if (adjustedHeight - roundedHeight >= gPointScaleFactor / 2.0) {
roundedHeight += gPointScaleFactor;
if (adjustedHeight - roundedHeight >= pointScaleFactor / 2.0f) {
roundedHeight += pointScaleFactor;
}
node->layout.dimensions[YGDimensionWidth] = roundedWidth;
node->layout.dimensions[YGDimensionHeight] = roundedHeight;

const uint32_t childCount = YGNodeListCount(node->children);
for (uint32_t i = 0; i < childCount; i++) {
YGRoundToPixelGrid(YGNodeGetChild(node, i));
YGRoundToPixelGrid(YGNodeGetChild(node, i), pointScaleFactor);
}
}

Expand Down Expand Up @@ -3427,7 +3426,7 @@ void YGNodeCalculateLayout(const YGNodeRef node,
YGNodeSetPosition(node, node->layout.direction, parentWidth, parentHeight, parentWidth);

if (YGConfigIsExperimentalFeatureEnabled(node->config, YGExperimentalFeatureRounding)) {
YGRoundToPixelGrid(node);
YGRoundToPixelGrid(node, node->config->pointScaleFactor);
}

if (gPrintTree) {
Expand Down
4 changes: 2 additions & 2 deletions yoga/Yoga.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ WIN_EXPORT void YGLog(YGLogLevel level, const char *message, ...);

// Set this to number of pixels in 1 point to round calculation results
// If you want to avoid rounding - set PointScaleFactor to 0
WIN_EXPORT void YGSetPointScaleFactor(float pixelsInPoint);
WIN_EXPORT void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint);

// YGConfig
WIN_EXPORT YGConfigRef YGConfigNew(void);
Expand All @@ -235,7 +235,7 @@ WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config,
WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config,
const YGExperimentalFeature feature);

// Using the web defaults is the prefered configuration for new projects.
// Using the web defaults is the prefered configuration for new projects.
// Usage of non web defaults should be considered as legacy.
WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled);

Expand Down

0 comments on commit 406c8a2

Please sign in to comment.