There are a large number of interlocking text-related bugs related to text frame content offsets. I tried to fix these in bug 385270 but I got it wrong and had to back out for M7. The underlying problems remain. I want to write down what's going on partly to keep my own head straight and also to get feedback.
Recap: text frames store a "content offset" and "content length", indicating the substring of the frame's DOM text node that the frame is responsible for. Historically, these fields have been lazily updated during reflow: the basic invariant is that frames that "have been reflowed" have correct offset and length, but for frames that "need to be reflowed" the offset and length fields should be considered invalid. Therefore reflow sets the offset and length fields. Bidi resolution also sets them, after which reflow updates them. This is troublesome because code that manipulates text frames has to be aware of the possibility that the offset and length are bogus. There are activities such as textrun construction that may touch text frames that have been reflowed and text frames and haven't. To address this, my patch in bug 385270 attempted to impose the invariant at all times that the content ranges for the text frames associated with a text node form a partition of the node's text --- i.e. they do not overlap and their union is all the text of the node. The main change required to achieve this was to have reflow and AdjustOffsetsForBidi (called by bidi resolution) update the offsets of next-in-flows when the frame's associated text grows or shrinks; if the frame gets more text, we shrink the next-in-flows accordingly, and if the frame loses text, that text gets associated with the next-in- flow. This failed for a couple of reasons. One reason is that the bidi resolver only looks at a single block frame at a time, when it really needs to look at an entire block continuation chain at a time (and those frames' overflow lines) --- e.g. bidi resolution for an element in columns should process all the columns at once. When a text node spans columns, the bidi resolver ends up associated all the text in the node with the frame in the column it's processing, so the frame's content range overlaps with the content range of the frame in another column. It's not clear how hard this would be to fix in the bidi resolver. Another, more fundamental issue concerns regular inline reflow. When a text frame breaks for the first time, we set its length to the length of the text before the break, and return to block layout. At this point there is no next-in-flow and no frame mapping the rest of the text, thus our invariant is violated. Normally we'd hope that a continuation frame is created "soon" and therefore the invariant is restored. However in some cases that doesn't happen: sometimes we decide to push the text frame we reflowed to the next line and try to reflow it again there. Sometimes that next line overflows the block and so we push it to the next column or page... so the continuation frame might not be created for a long time, or might never be created if the text frame fits in its new location. Here's an alternative approach. Let's get rid of the content length field, and consider the text mapped by a text frame to be the text between the frame's starting offset and the frame's next continuation's starting offset (or the end of the text node if there is no next continuation). Then we just need to ensure that content offsets do not decrease along a continuation chain, then we're guaranteed to have a good partition of the text. When we reflow a text frame, we update the offsets of next-in-flows to indicate how much text is being mapped by the current frame. If there is no next-in- flow, we set a field in the current frame --- like the current length field, but more like a temporary hint --- to indicate where a new continuation should start. Until the new continuation is created, the current frame is still considered to be mapping that text --- this is how the issue in the above paragraph is fixed. The bidi resolution problem still exists. I'm not sure if we should tackle that head on, or try to work around it by having AdjustOffsetsForBidi do clever things to maintain our invariant. Since all we have to do is ensure the offsets are non-decreasing along the continuation chain, it might be possible to ensure that in a reasonable way without messing with the resolver for 1.9. _______________________________________________ dev-tech-layout mailing list [email protected] https://lists.mozilla.org/listinfo/dev-tech-layout

