[webkit-dev] Can someone explain tx/ty?

Maciej Stachowiak mjs at apple.com
Mon Aug 23 02:33:04 PDT 2010

On Aug 23, 2010, at 12:51 AM, Eric Seidel wrote:

> I believe int tx, int ty -- which we see sprinkled around the
> rendering tree -- are the offset from the top left corner of the
> current renderer's parent to the containing block.  Is that correct?
> In SVG we use IntSize containingBlockOffset in the rare places we have
> to deal with this RenderBoxModelObject-only concept.
> I've long considered fixing renders to use IntPoint and IntSize
> instead of x, y, tx, ty, but to do that, I need to make sure I
> understand what tx, ty are, and what name they should have as an
> IntSize.

I think it would be good to use IntPoint and IntSize in more places in the render tree.

My understanding of tx/ty is imperfect so you may want to have a rendering guru weigh in, but I believe it works like this:

- x(), y() are a renderer's position in the coordinate system of its parent

- tx, ty are the origin of the parent's coordinate system relative to the origin for its layer. When a layer paints, it establishes a CTM such that its own origin is 0, 0 (I think).

When a renderer paints, the first thing it does is add its own x() and y() to tx and ty, and it passes the new values of tx and ty to its children.

There's two ways to express this in size/point terms. First, some rules for Point / Size math:

- You can add a Size to a Point to get a new Point.
- You can add a Size to a Size to get a new Size.
- It doesn't make logical sense to add two Points, so the operation doesn't exist. Points are absolute and Sizes are relative; you can't add two absolutes.

The more obvious way, given the variable names, would be to make x(), y() an IntPoint, with a name like originInParentCoordinates() (hopefully less verbose, but you get the idea). tx, ty could be named parentOffsetFromLayerCoordinates or something. This seems to be the intent of the names - that x,y is a point and tx, ty is a translation. But this doesn't work in point/size logic. You repeatedly add x(), y() to tx, ty to get a new tx, ty. But that means you're adding a point to a size and expecting to get a new size - but that's not how it works.

The way that works is to reverse the logic. tx, ty becomes IntPoint parentOrigin. x(), y() becomes IntSize offsetFromParent(). You add your offsetFromParent() to your parentOrigin to get the parentOrigin you pass from your children. This reverses the idea of which is the point and which is the offset, but it fits the axioms of point/size arithmetic and I believe it is ultimately more logical. You can see this in part from the shorter names. The first line in a ::paint() method would be IntPoint origin = parentOrigin + offsetFromParent(). How sweet is that?

(Note: I omitted many details here, such as accounting for scroll offsets. Renderers that are scrolled account for the scroll offset in the tx, ty they pass their children even though this is not strictly their *own* origin.)

BTW I have rewritten parts of render tree logic before to use IntPoint, IntSize, and point/size operations instead of dealing with individual coordinates, and I always found the code far more readable. This is particularly so when I stopped to figure out what should be a size and what should be a point based on the axioms of point/size arithmetic.


More information about the webkit-dev mailing list