Re: [CSSOM] Revisiting transforms and getBoundingClientRect()

On Wed, Aug 28, 2013 at 3:21 PM, Robert O'Callahan <robert@ocallahan.org> wrote:
> [Reviving old thread]

Yay!

> On Fri, Sep 9, 2011 at 7:01 AM, Simon Fraser <smfr@me.com> wrote:
>>
>> The basic pieces seem to be:
>>
>> 1. Get an element's padding, content, border and margin boxes relative to
>> its own border-box, as rects.
>> 2. Convert a rect to a quad.
>> 3. Map arbitrary point from one element to another.
>> 4. Map arbitrary quad from one element to another (mapping 4 points)
>
>
> Splitting the pieces up this way has a problem: with CSS Regions (or CSS
> Overflow), it's possible for a CSS transform to apply to one box of an
> element, but not another --- when one fragment flows into a container that
> has a CSS transform, and another fragment flows into a different container
> with no transform. In such a case, step 1 is lossy :-(.
>
> Therefore I think we need to offer a way to get the boxes as a list of
> quads. In that case, I think we may as well offer coordinate-space
> conversion in the same call.
>
> Part 3 has been more recently addressed:
> http://lists.w3.org/Archives/Public/public-pointer-events/2013JanMar/0099.html
>
> So here's my proposal:
>
> Rename ClientRect to CSSRect.
>
> [Constructor(CSSPoint, CSSPoint, CSSPoint, CSSPoint),
>  Constructor(ClientRect)]
> interface Quad {
>   readonly attribute CSSPoint p1; // 2D only (z,w not present)
>   readonly attribute CSSPoint p2;
>   readonly attribute CSSPoint p3;
>   readonly attribute CSSPoint p4;
>   readonly attribute CSSRect bounds;
> };
>
> [Constructor(sequence<Quad>)]
> interface QuadList {
>   readonly attribute unsigned long length;
>   getter Quad item(unsigned long index);
>   readonly attribute CSSRect bounds;
> };
>
> enum BoxType { "margin", "border", "padding", "content" };
> dictionary BoxQuadOptions {
>   attribute BoxType box; // defaults to "border"
>   attribute Node relativeTo; // defaults to viewport
> };
>
> partial interface Node {
>   QuadList getBoxQuads(BoxQuadOptions options);
>   Quad convertQuadFromNode(Node from, Quad quad);
>   Quad convertRectFromNode(Node from, CSSRect rect);
> };
>
> Edge cases handled as in
> http://lists.w3.org/Archives/Public/public-pointer-events/2013JanMar/0099.html
> and following thread.
>
> I've proposed packing getBoxQuads parameters into a dictionary. Separate
> getMarginBoxQuads etc methods, each with an optional "Node relativeTo"
> parameter, would work too, but I think would be less easily extended in the
> future. I also think that in this case naming the "relativeTo" parameter is
> a good thing (e.g. "node.getBoxQuads({relativeTo:otherNode})" seems easier
> to read than "node.getBoxQuads(otherNode)").
>
> Any thoughts?

Your naming is inconsistent.  Merging with the other linked thread, we
have "CSSRect", "Quad", and "DOMPoint".  You seem to have renamed the
last one to "CSSPoint" in this email, which helps, but I'm still left
wondering why it's not "CSSQuad".  (I kinda liked DOM as the prefix
for all of them, on the assumption that these things'll be useful for
more than just CSS.  Maybe we could divorce it further from "where
it's specced" notions and call them LayoutPoint/Rect/Quad?  I'd like a
name that doesn't have much friction with using these in a 3d geometry
library.)

I like the signature of getBoxQuads methods, and agree that a named
"relativeTo" arg is worth the extra typing.

The signatures of the convert* methods here and in the other linked
thread constantly confuse me.  Perhaps a better naming scheme in the
IDL would help, like "sourceNode" and "sourceQuad"?  Also, the name
suggests a "quad, node" ordering, but the actual signature is the
opposite.

I don't understand why getBoxQuads lets you specify which box of the
node you want, but the convert* methods don't.  It seems equally
useful/necessary there - if you pulled a quad off of the padding box
of something, manipulated it, and then want to convert it into another
coordinate space, you have to ensure that the conversion knows it's
relative to the padding box.

Maybe we could unify the three convert* methods under a slightly more
generic name (convertCoordsFromNode?) and just making the
quad/rect/point arg a union?  That would mean that it has to return a
union of quad and point, but I think that's just clumsy in WebIDL, not
in real life.  (It would also make it easier to extend into handling
Tris, if we ever find a need to do so, but this isn't an important
thing.)

Could we make Rect a subtype of Quad?  It would make it easier to
write generic code that handles quads - it's annoying that right now
if we have a mix of Rects and Quads I'd need to discriminate them in
my code, or would have to manually convert the former into the latter.

The QuadList interface is terrible. :/  We have better ways to do this
in WebIDL now - make it an [ArrayClass].  (Maybe we can change
ClientRectList as well?)

Otherwise, hell yeah, I'm glad to see you still poking at this.  Let's
get it specced and implemented!

~TJ

Received on Wednesday, 28 August 2013 22:53:27 UTC