- From: Dael Jackson <daelcss@gmail.com>
- Date: Wed, 26 Dec 2018 17:51:31 -0500
- To: public-houdini@w3.org
- Cc: CSS WG <w3c-css-wg@w3.org>
================================================= These are the official Houdini Task Force minutes. Unless you're correcting the minutes, please respond by starting a new thread with an appropriate subject line. ================================================= Typed OM -------- - Resolving values with external information (Issue #798) needs more time to develop a full proposal. - The plan is to drop CSSPositionValue from the first level unless a solution is found for representing positions. (Issue #817) - A single value when a list is appended will be handled by silently dropping the single value and making it a list. (Issue #823) - RESOLVED: Make TypedOM compatible with future Array-like plans, per issue #825. Layout API ---------- - There were concerns that the solution for float representation and rounding to fractional units could be fragile and have problems, for example, due to differences in rounding and representation within the layout engine or pixel-snapping (engines try to ensure certain lengths, such as border widths, resolve to the same number of pixels given the same abstract length). Google will experiment with their implementation to see if there are problems. (Issue #830) ===== FULL MINUTES BELOW ====== Agenda: https://github.com/w3c/css-houdini-drafts/wiki/TPAC-F2F-October-2018 Scribe: heycam Typed OM ======== Status Update ------------- https://github.com/w3c/css-houdini-drafts/issues?utf8=%E2%9C%93&q=+is%3Aissue+label%3AAgenda%2B++sort%3Aupdated-desc TabAtkins: I want to get a bunch more work on this done before next meeting TabAtkins: More significant updates in the near future TabAtkins: We have some impl internally again, brought up some interesting issues Resolve values to a px with external information ------------------------------------------------ https://github.com/w3c/css-houdini-drafts/issues/798 TabAtkins: If all of the units you have in a math value are compatible with pixels e.g. then you can always resolve them to a single px TabAtkins: If you have combinations of values that aren't directly resolvable, there's no way to resolve them TabAtkins: since the custom layout API works mostly in px values, it would be useful to give people more direct control over how they can simplify them down to px <TabAtkins> https://github.com/w3c/css-houdini-drafts/issues/798#issuecomment-415555133 TabAtkins: So we add an options bag to the to() and toSum() functions TabAtkins: giving extra information for resolving the values TabAtkins: In particular, the element being resolved on (for ems etc.), the property it's on (so font-size can properly resolve to parent element), and what a % should resolve to TabAtkins: Going with this explicit % resolution thing to avoid some problems with some properties resolving %s against different sizes TabAtkins: This makes it more explicit with cases like the layout API, where you have an available space, and you can just pass that in rather than finding a property to pretend it's being resolved as TabAtkins: I think that lets us resolve all the units TabAtkins: In particular, a comment further down suggests that we don't have a default value, so if you don't pass an element, resolve like MQs do, with no context TabAtkins: Right now, if you call to() without this information and it needs it, it throws emilio: The layout API doesn't have access to any element, right? TabAtkins: Yes emilio: Can we instead pass what the function depends on explicitly? what's the expected thing if you pass an element to there, I assume you have to do style updates etc.? emilio: What happens if that element's not in the flat tree etc.? emilio: Would be nice to be more explicit about which data you're depending on emilio: then people can use the no context thing without having magic TabAtkins: There's a lot of information. which font's being used. it's possible to enumerate this emilio: Instead of getting a font and doing font matching, you may as well .... I guess there's no way to get ex height without script TabAtkins: A possibility is to allow you to pass an element, but also enumerate all the things that the various relative units can depend on TabAtkins: and if you don't pass a unit, that's the info you have to work with TabAtkins: and if you use a unit but no way to determine what that is, continue to throw emilio: If you need to download fonts to make this work... TabAtkins: That's what we have to do emilio: Normally you wait for a computed value, which triggers all that emilio: That only happens if you actually lay out the element TabAtkins: And the assumption here is you are doing something layout-y but not with an element emilio: Let's say you call this function from a layout worklet with a given font TabAtkins: Does the layout trigger the font load somewhere? TabAtkins: Good question TabAtkins: Possibly emilio: Does it do it sync? probably not emilio: You can't make it sync TabAtkins: I think then we should remove the element resolver, figure out what relative units we can easily resolve on, e.g. asking for font-size, other font relative ones are a bit hard for now TabAtkins: and then if you try to use an ex unit to px, we just throw TabAtkins: Then we can remove the property too fremy: If you still want the behavior to pass an element, you can have another element, and it returns the properties you would fill in TabAtkins: One of those dictionaries dbaron: I'm not convinced you can remove the property dbaron: If you're doing it from the element, you still need to know font-size / line-height behave differently for em and lh units TabAtkins: I'm suggesting that just like the 100% line, where you explicitly indicate what the resolves to, you just supply what them resolves to TabAtkins: and then also supply a function that can extract that from an element automatically fremy: CSSNumericValue -- is that calc or more stuff? TabAtkins: Everything fremy: Can just create a 1em and call to emilio: Layout API functions could need 1vmax, you need to expose viewport size to those functions emilio: not sure if you want to? <dbaron> The function to extract from an element automatically would need a property. iank: No access to viewport info iank: It's not necessary iank: The side effect of exposing that info is that when you resize that viewport, you'd need to call every layout function iank: since it's a side input TabAtkins: This would be an implicit dependency TabAtkins: unless we made it explicit somehow fremy: We could add a function in the worklet, before calling it viewport sizes are 0, and only after you can use it... TabAtkins: We have a case for later registrations of dependencies iank: Probably you want to do this in the layout registration dictionary iank: You don't know which global scope you're doing to run it in fremy: The other option is to create custom properties that would be 1vmin, etc., type them to be lengths, then you'll get the value fremy: it's a bit handwavy but it does work iank: If this becomes a common pattern, in layout options, say that resolve vw/vh against the real thing iank: but part of the precedent for resolving to 0 is what happens when you set a font-size in an offscreen canvas context, it resolves to 0 TabAtkins: That's different from how MQs work iank: Not saying that's good or bad but that's the precedent TabAtkins: I think that's all the feedback I need; I will come back with a more mature proposal in the future Drop CSSPositionValue --------------------- github: https://github.com/w3c/css-houdini-drafts/issues/817 TabAtkins: CSSPositionValue was in the first draft TabAtkins: Assumes every position is a horiz/vert offset TabAtkins: Now they can be logical TabAtkins: Not certain how best to represent this flexibility in the object shape TabAtkins: until I do I plan to drop it from the draft and impl TabAtkins: If anyone has ideas for representing these values would love help astearns: There have been a number of things we've dropped astearns: Are we tracking those in any way? astearns: Next level draft? TabAtkins: I shall soon TabAtkins: We did a publish a while ago, need to do another one soon TabAtkins: Before EOY I'll get ready for a new draft TabAtkins: and I'll have a substantial changes section to outline what happened Clarify list-valued properties ------------------------------ github: https://github.com/w3c/css-houdini-drafts/issues/823 TabAtkins: This was brought up by one of our engineers TabAtkins: I was hoping at the start this issue wouldn't occur. I was hoping to split props into list values and single values TabAtkins: every prop would be one or the other TabAtkins: anders pointed out we have several props that at minimum have a neutral value, but sometimes have more than that TabAtkins: and the list value / single value split is not enforced in custom props either TabAtkins: You can always define [ length+ | number+ ] TabAtkins: Not handling that well TabAtkins: So rather than declare props to be list valued or single valued, declare top level productions as being list valued or single valued in a given prop TabAtkins: e.g. content TabAtkins: Some of the productions will be single valued, and they can't be used with the append() methods TabAtkins: Some are multi-valued, and can be used with the append() methods TabAtkins: and if you do the wrong one, and you call styleMap.append("counter-reset", "none") TabAtkins: I believe we'll throw in that case TabAtkins: One thing I'm not sure is how to handle the case where it's currently a single value, and you append a list production TabAtkins: e.g. it's currently set to none, and you want to append real values TabAtkins: The most common case is none, I'd like that to be easier to handle TabAtkins: So I'd like to make that silently drop the single value, and turning it into a multi-value production instead TabAtkins: Not sure about this, may be more consistent to throw here TabAtkins: I believe this design in general, is the way to go to handle all possible props properly TabAtkins: It's not a significant complexity increase TabAtkins: It'll be a bit more work continuing we need to make sure they're properly tracked heycam: What if we change a property from single-value length to multi-value length? TabAtkins: In that case the original length would be classified as a multi-value heycam: So in the updated property that would be defined as a multi-value thing TabAtkins: So let me know if you have opinions on this TabAtkins: Otherwise I'll resolve it like this and edit it in fremy: How you define that syntax, how would you write down your declaration to say this is single valued or list valued? TabAtkins: CSS in the specs will define this TabAtkins: Don't have to do that in the API side fremy: For custom properties TabAtkins: Right now, custom props are either a single value or there's a + in there TabAtkins: but once we had the # one, those will be multi-valued Figure out Array-likes ---------------------- github: https://github.com/w3c/css-houdini-drafts/issues/825 TabAtkins: So Typed OM has had a handful of array-like interfaces since the beginning TabAtkins: Been clashing with Anne and Domenic on how to handle these TabAtkins: Last week Domenic and I sat down to look at plausible future plans TabAtkins: for array-likes in the future, it should indeed be an Array subclass TabAtkins: So Array.prototype stuff works, Array.isArray works TabAtkins: and then at some point, either as just a spec concept, or possibly as an author facing API, there'll be a way to hook get/set indexes TabAtkins: Although they look like data properties, there is still some magic TabAtkins: that intercepts a get/set so it can update length TabAtkins: just set TabAtkins: Nothing specwise that stops us using that hook TabAtkins: This has some implications for the array-likes in typed OM TabAtkins: In particular, there are 3 arrays-likes -- CSSMathArray TabAtkins: It's declared to descend from CSSStyleValue TabAtkins: It's the array that hold calc arguments TabAtkins: Could switch this over to a new Array subclass TabAtkins: The other two, CSSUnparsedValue -- for representing var()s -- and CSSTransformList -- which reps transform lists TabAtkins: both are array-like and you can array index them TabAtkins: There's are directly useful as values you can set to properties, so can't change them from being CSSStyleValue TabAtkins: Probably then we'll move the segments / functions to a property hanging off them, make them array-likes that inherit from Array TabAtkins: and have hooks that do type checks to ensure only transform functions etc. are set TabAtkins: In anticipation of this working later on, these will still have getter on them for now TabAtkins: When we do switch to the real model, worked out in IDL, we can just remove that and there'll be very little if any behavior change bz: Have you talked to JS engine implementors about this? TabAtkins: I talked to domenic and adam klein about this bz: In particular the idea of generically hooking set on arrays they're ok with? TabAtkins: We can do this right now bz: Sort of bz: It's very very special cased for length updates bz: In the TC39 spec handwaves it bz: In impls for performance ... TabAtkins: So they wouldn't be naked Arrays with magical behavior TabAtkins: Right now indexed setters get the same array-looking thing and they are optimized (not quite as good as naked arrays) bz: So you would be modifying Array.isArray to do something here TabAtkins: Yes bz: And deal with subclass construction bits TabAtkins: domenic has some feedback in TC39 for this fremy: One question. the segments array in CSSUnparsedValue would not be read only? TabAtkins: It's not currently read only TabAtkins: It only takes strings and var references TabAtkins: We'll continue doing type checking to make sure other values aren't set in there andrew: You don't want to make the transform components subclasses andrew: They have to descent from array andrew: What do we do for values we return? TabAtkins: CSSTransformList remains a CSSStyleValue TabAtkins: but it has a prop that is an array-like andrew: If you register a prop with that syntax TabAtkins: Transform functions are CSSStyleValues as well TabAtkins: The list inside it andrew: ok, misunderstood fremy: If we have the segments thing, it's better fremy: but there is still the case for when you upgrade CSSUnparsedValue to another thing fremy: You should not break the compat fremy: If right now we don't have a position thing TabAtkins: No, unparsed value is not the generic value class TabAtkins: that's CSSStyleValue fremy: CSSUnparsedValue is only for var? TabAtkins: Yes bz: What are the semantics of setting .length on these things? TabAtkins: Still a great question TabAtkins: Not 100% sure, but more than likely I'll decide it's fine to have undefined/holes TabAtkins: and those are ignored fremy: In the meanwhile can't we use a normal Array with no checking fremy: Well it's not compatible with you switch bz: Code that used to work will start throwing exceptions TabAtkins: This is detailed enough to know what the direction will be. Let me know you thoughts RESOLVED: Make TypedOM compatible with future Array-like plans, per #825. Layout API ========== Precision and rounding in layout API ------------------------------------ github: https://github.com/w3c/css-houdini-drafts/issues/830 iank: I wanted to write down the problem clearly iank: As specced now, with availableInlineSize: 10.13, the internal representations in each engine will be different iank: I believe Blink/WebKit will be 10.125, Gecko will be 10.133, Edge will be 10.13 iank: Similarly, say that child is auto sized, the value that you will get out in JS will be 10.125 for Blink/WebKit, some ugly values near 10.33333 for the others iank: This is exposed right now <dbaron> Some of the ugliness is something that we could fix (by going directly from fixed-point to double rather than fixed-point to float to double) iank: If you set width:10.13px on an element, and you call getClientRects, you will get similar issues iank: Part of me thinks this is a non-issue iank: The thing I worry about with rounding is that you'll get potential tearing iank: Imagine if you're doing a flexbox-like thing iank: where you're distributing available space between children iank: With the current API you won't get any subpixel tear, but if you round inputs and outputs you will iank: You'll have to define the whole layout tree working on rounded precision mode eae: When you say rounding, you mean rounding to ints or to these values? iank: If you round to int values, going in and out of the engine, you might see tearing iank: If you're distributing some fractional space in a flexbox-like thing you can't do that iank: Also you'd need to specify the whole subtree works in rounded int precision smfr: What do you mean by tearing? iank: If you try to position the two fragments side by side, you'd get a gap iank: Similarly, the second class there is if you happen to be distributing some space that wouldn't get a gap, the element might be smaller bz: To be clear, the container being smaller than the elements is a problem anyway bz: Even with floats iank: The conversion to the JS float thing, it's still possible to get tears accidentally iank: but because the JS repr is high enough, converting from the internal fractional to JS to the internal fractional will result in the same fractional value chrishtr: What about pixel snapping? iank: We only do that at paint iank: We don't pixel snap any of the layout TabAtkins: Yes we do TabAtkins: border widths e.g. eae: Borders are very special emilio: Device pixels dbaron: There's a small class of things where you care about the with of the thing being the same across repeated occurrences dbaron: Borders, column rules, probably line heights as well dbaron: but for most other things we don't do internal snapping dbaron: You round to internal repr then snap edges to the nearest pixels iank: The pixel snapping borders we can repr that value in the LayoutEdges object bz: Presumably this is snapped to dev pixels here iank: Yes chrishtr: Blink currently snaps to CSS px eae: Not really chrishtr: In cases where the device pixel ratio is incorporated into zoom it's device pixels chrishtr: long term intention is to use device pixels smfr: Someone mentioned pixel snapping in border would happen at layout time? isn't purely a paint time operation? dbaron: For us it's a computed value time thing Rossen: For us it's also style Rossen: It matters for lower values, 1, 2, 3, px Rossen: but over 13, 14px it doesn't really matter dbaron: But it does matter for not getting the 1px gaps that you do the snapping before the layout calcs based on it dbaron: If you do layout calcs based on a non pixel snapped border, then snap it later, you'll sometimes get 1px gaps or overlaps Rossen: So we'll do the layout with fractional border sizes Rossen: then snap during paint dbaron: But you need to snap all the things next to that border during paint too or they won't line up Rossen: No they won't dbaron: Then your system is different in more complex ways from ours chrishtr: Is the intention to spec the rounding? iank: No chrishtr: Or just things that UAs may do? iank: My preference is to allow the UA to do internal rounding to the fractional repr and back iank: Main thing I want to avoid is the 1px tearing in layouts chrishtr: It should at least be said if the left/right edge of things are the same number, there should not be a tear eae: Can probably find a way to spec that chrishtr: You'd have to say the rounding and layout is the same, and that pixel snapping at paint time preserves that consistency iank: Yep Rossen: Does that work for you Simon? smfr: Yes I think so smfr: WebKit does some snapping of border widths as well smfr: I'm trying to understand when you're laying out fragments iteratively, does the browser tell you how much space is left? A floating point input smfr: with custom layout, call layoutnextfragment 3 times smfr: each time an input is the remaining space? iank: No you need to do that yourself iank: So you'll have some available size, layout first child, subtract the size of it in the JS double smfr: Was concerned about the conversions between JS doubles and the quantized values internally iank: Since it's handled by script it's always the JS doubles smfr: Trying to think of cases where the rounding would hurt you smfr: Maybe combining custom paint and layout smfr: you ask for a certain with with double precision smfr: then in paint ... iank: I think previously you've brought up trying to fit into the one fractional unit, and some engines will leave a tiny fractional unit over iank: In one you go into the next line, in another you'll have a skinny box for some reason iank: I think it's a super edge case fremy: My impression is that the only case where this could be an issue is where you do the data sharing between custom layout fremy: You could share with full precision, and on the other side of the API you'd get it fremy: but I also don't expect this to be a problem <TabAtkins> Found that the internal->JS->internal conversion is always accurate up to (10^15)px; at 10^16 there's a few rounding errors with Microsoft's precision. <TabAtkins> http://software.hixie.ch/utilities/js/live-dom-viewer/saved/6318 <astearns> you can just add a flag in Blink to use 1/60 or 1/100 internally <bkardell> astearns are you suggesting google could add that capability or saying that it already exists? <astearns> ian said he did it just now :) <eae> bkardell/astearns it does not exist but we could potentially do it as an experiment. smfr: As a data point, this same problem also happens in media timing values smfr: Currently they're all floating point, but there've been discussions about turning them into a rational type smfr: They're trying to solve some similar way here iank: I think there's been talk in JS previously about having value types TabAtkins: They're not ready yet iank: They've been vapourware for a while iank: but the intention would be to work in that fractional type iank: We shouldn't depend on that iank: Could imaging a future where JS does get that fractional type, see if it's compatible to change to that iank: or otherwise add an option to opt in to it fremy: This transformation is a rounding iank: It's a rounding to the fractional representation fremy: Can we floor rather than round? fremy: Otherwise if you divide by 7, all your 7 column objects, you give them avail size / 7 fremy: then you have a layout where each gets the size they can. if each is rounded up, the sum will be bigger than 100% and you'll wrap fremy: Better to floor fremy: You make sure the sum will all fit TabAtkins: Flooring starts loosing this internal -> JS double -> internal relationship more quickly eae: You can have a situation where you have a lot of space at the end eae: which is also not desirable fremy: People writing the layout will pay attention to this smfr: Has anyone tried using the prototype to see if it's a problem? fremy: The prototype is only in one browser smfr: Still possible to make layouts with hairline gaps fremy: I've not tried but I guess it's possible iank: We can see if people run into it iank: so far surma and fremy haven't run into it smfr: Your masonry layout wasn't trying to fit something into something with a border, not obvious there's a gap iank: We can experiment with prototypes with borders to see if we can get hairline gaps fremy: Grid has the opportunity to have these options, but you can position things at particular points, no wrapping fremy: Even with 7 column grids, you place them before sizing, so it doesn't matter fremy: We should try the flexbox-like thing iank: I think the action item on us is to play with our impl to see if we can break iank: but sounds like people are relatively fine with the float representation and rounding to fractional units internally iank: We can report back to the group <br dur=1hr>
Received on Wednesday, 26 December 2018 22:52:28 UTC