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

Add yoga::Style::resolve() for ahead-of-time computed whole style #1455

Open
NickGerleman opened this issue Nov 8, 2023 · 2 comments
Open

Comments

@NickGerleman
Copy link
Contributor

NickGerleman commented Nov 8, 2023

What

We have different adhoc ways of resolving and caching from the user input style. These can often be repeated and expensive (e.g. for edge value resolution), and the APIs exposed for resolution are inconsistent.

We pass that computed style through yoga::calculateLayoutInternal, and try to remove cases where we pass a whole child Yoga node, to make it easier to reason that only layout results are being mutated.

Example

// Precomputes the full style, caching the last computed value for return
// if args match, and style not dirty
auto computedStyle = style.resolve({
  .ownerWidth = ownerWidth,
  .ownerHeight = ownerHeight,
  .viewportWidth = viewportWidth,
  .viewportHeight = viewportHeight,
});

References:

  1. https://www.w3.org/TR/css-cascade-4/#computed
@nicoburns
Copy link
Contributor

nicoburns commented Nov 15, 2023

Not sure if you were intending to resolve percentages as part of this function (the ownerWidth/ownerHeight parameters suggest to me that you are), but it's worth noting that there can be cases where some percentages need to recompute and others don't (e.g. mid-way through laying out a node you want to recompute percentage gap but not percentage width). In which case such an "all or nothing" function may be awkward.

Taffy's solution to this is keep a struct of resolved styles on the stack of the equivalent function of calculateLayoutInternal, which we update incrementally throughout the layout process (and pass through to sub-functions by reference).


Also, as a point of terminology: "computed" values do not resolve percentages (and they couldn't because determining "computed" values is part of the style pass rather than the layout pass in browsers, and in the general case you don't have a value to resolve percentages against until you run layout). See: https://www.w3.org/TR/css-cascade-4/#stages-examples.

If you're not resolving percentages then this comment may not be relevant.

@NickGerleman
Copy link
Contributor Author

NickGerleman commented Nov 15, 2023

Also, as a point of terminology: "computed" values do not resolve percentages

That’s a good clarification. I missed the table, but saw “Computing a relative value generally absolutizes it” and reference to percentage computation against reference, and placed the phases together.

Computed style purely derived from style is convenient to work with because it’s only ever dirtied when the style changes, and we do already do repeated work for it during layout (e.g. all the “edgeValueForColumn” type of work.

I suspect we want to add caching for resolved absolute values from relative, given the same reference, if resolution can be more expensive (i.e. if Yoga or its user needs to evaluate a parser CSS math function) I’m not quite sure what lifetime and layering for that. E.g. measure cache is kept around after the layout, but I’m not sure if a more persistent cache makes sense here.

I was looking as having computed value accessor directly accept the reference value for a single value at once to be able to cache more granularity if we needed it.

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

2 participants