Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why can't we round node width/height directly in roundLayoutResultsToPixelGrid()? #1574

Open
1 task done
kennethpu opened this issue Feb 7, 2024 · 3 comments
Open
1 task done

Comments

@kennethpu
Copy link

Report

In PixelGrid.roundLayoutResultsToPixelGrid() it appears that we are calculating a node's rounded width/height as follows:

  1. Calculate the start position of the node.
const double absoluteNodeLeft = absoluteLeft + nodeLeft;
  1. Using the start position and computed width, calculate the end position of the node.
const double absoluteNodeRight = absoluteNodeLeft + nodeWidth;
  1. Calculate rounded node width/height as the difference between the rounded start/end positions of the node.
node->setLayoutDimension(
    roundValueToPixelGrid(
        absoluteNodeRight, 
        pointScaleFactor, 
        (textRounding && hasFractionalWidth), 
        (textRounding && !hasFractionalWidth)
    ) -
    roundValueToPixelGrid(
        absoluteNodeLeft, 
        pointScaleFactor, 
        false, 
        textRounding
     ),
     Dimension::Width);

It's not clear to me why we need to calculate rounded width/height in this way as opposed to rounding the width/height values directly, and it also seems like this may introduce rounding errors as noted in this previously opened issue (#901). Curious if the proposed solution on that issue has merit or if there are other issues not being considered.

As an iOS developer utilizing a fork of Yoga (really appreciate this project btw!) I'm also curious if you foresee any issues with tweaking the rounding logic on our fork to more closely mirror Apple's strategy of rounding down origin values and rounding up size values to the nearest pixel boundary. Are there other parts of the layout algorithm we would need to update for consistency?

@NickGerleman
Copy link
Contributor

I would love to change how layout rounding works in terms of how it's executed, but haven't put a lot of thought into it's underlying rounding logic. We have seen real bugs from it.

A goal of this style of rounding is to not introduce "gaps", so it makes sense for the start position reference to be the previous rounded pixel I think.

The text rounding flag can on the other hand introduce overlaps, which is also wrong.

@nicoburns
Copy link
Contributor

Yoga's algorithm is indeed quite clever in it's avoidance of gaps in the resultant layout. The commit that introduced the current rounding mode to Yoga (aa5b296) has an excellent writeup on the motivation. I believe Apple's strategy will result in 1px overlaps in some cases, which is perhaps not so bad (this definitely seems to me like a problem where there isn't really one best solution) but is something to bear in mind.

@nicoburns
Copy link
Contributor

Regarding your having a fork of Yoga, are there also other changes that you have made locally? And would you be interested in upstreaming those?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants