michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0:

michael@0: Line Layout

michael@0: Line layout is the process of placing inline frames horizontally (left michael@0: to right or right to left depending on the CSS direction property value). michael@0: An attempt is made to describe how it works. michael@0:

nsLineLayout is the class that provides support for line layout. The michael@0: container frames nsBlockFrame and nsInlineFrame use nsLineLayout to perform michael@0: line layout and span layout. Span layout is a subset of line layout used michael@0: for inline container classes - for example, the HTML "B" element). Because michael@0: of spans, nsLineLayout handles the nested nature of line layout. michael@0:

Line layout as a process contains the following steps: michael@0:

    michael@0:
  1. michael@0: Initialize the nsLineLayout object (done in nsBlockFrame). This prepares michael@0: the line layout engine for reflow by initializing its internal data structures.
  2. michael@0: michael@0:
      michael@0:
  3. michael@0: Reflowing of inline frames. The block code uses nsLineLayout's ReflowFrame michael@0: method to reflow each inline frame in a line. This continues until the michael@0: line runs out of room or the block runs out of frames. The block may be michael@0: reflowing a span (an instance of nsInlineFrame) which will recursively michael@0: use nsLineLayout for reflow and placement of the frames in the span.
  4. michael@0: michael@0:


    Note that the container frames (nsBlockFrame/nsInlineFrame) call michael@0: nsLineLayout's ReflowFrame method instead of having the line layout code michael@0: process a list of children. This is done so that the container frames can michael@0: handle the issues of "pushing" and "pulling" of frames across continuations. michael@0: Because block and inline maintain different data structures for their child michael@0: lists, and because we don't want to mandate a common base class, the line michael@0: layout code doesn't control the "outer loop" of frame reflow. michael@0:
      michael@0:

  5. michael@0: Finish line layout by vertically aligning the frames, horizontally aligning michael@0: the frames and relatively positioning the frames on the line.
  6. michael@0:
michael@0: nsLineLayout is also used by nsBlockFrame to construct text-run information; michael@0: this process is independent of normal line layout is pretty much a hack. michael@0:

When frames are reflowed they return a reflow status. During line layout, michael@0: there are several additions to the basic reflow status used by most frames: michael@0:

michael@0: The handling of the reflow status is done by the container frame using michael@0: nsLineLayout. michael@0:

michael@0: Line Breaking

michael@0: Another aspect of nsLineLayout is that it supports line breaking. At the michael@0: highest level, line breaking consists of identifying where it is appropriate michael@0: to break a line that doesn't fit in the available horizontal space. At michael@0: a lower level, some frames are breakable (e.g. text) and some frames are michael@0: not (e.g. images). michael@0:

In order to break text properly, some out-of-band information is needed michael@0: by the text frame code (nsTextFrame). In particular, because a "word" (a michael@0: non-breakable unit of text) may span several frames (for example: "<B>H</B>ello michael@0: there" is breakable after the "o" in "ello" but not after michael@0: the "H"), text-run information is used to allow the text frame to michael@0: find adjacent text and look at them to determine where the next breakable michael@0: point is. nsLineLayout supports this by keeping track of the text-runs michael@0: as well as both storing and interrogating "word" state. michael@0:

michael@0: White-space

michael@0: To support the white-space property, the line layout logic keeps track michael@0: of the presence of white-space in the line as it told to reflow each inline michael@0: frame. This allows for the compression of leading whitespace and the compression michael@0: of adjacent whitespace that is in separate inline elements. michael@0:

As a post-processing step, the TrimTrailingWhiteSpace logic is used michael@0: to remove those pesky pices of white-space that end up being placed at michael@0: the end of a line, that shouldn't really be seen. michael@0:

To support pre-formatted text that contains tab characters, the line michael@0: layout class keeps track of the current column on behalf of the text frame michael@0: code. michael@0:

michael@0: Vertical Alignment

michael@0: Vertical alignment is peformed as a two and a half pass process. The first michael@0: pass is done during nsInlineFrame reflow: the child frames of the nsInlineFrame michael@0: are vertically aligned as best as can be done at the time. There are certain michael@0: values for the vertical-align property that require the alignment be done michael@0: after the lines entire height is known; those frames are placed during michael@0: the last half pass. michael@0:

The second pass is done by the block frame when all of the frames for michael@0: a line are known. This is where the final height of the line michael@0:
(not the line-height property) is known and where the final half pass michael@0: can be done to place all of the top and bottom aligned elements. michael@0:
  michael@0:

michael@0: Horizontal Alignment

michael@0: After all frames on a line have been placed vertically, the block code michael@0: will use nsLineLayout to perform horizontal alignment within the extra michael@0: space. michael@0: michael@0: