Story Library
Home   Hierarchy   Classes   Files   Functions   Modules   Pages  

Composition Overview

Page Geometry

The following diagrams show the essential page geometry.

A Story::CColumn is a vertical block of lines. Each line is implemented by a Story::CLineShape, which breaks the line's rectangle into smaller rectangles (using Story::CLinePartBox) allowing for paragraph indents, drop caps and overlapping wrap shapes. Each line part box is occupied by 1 Story::CLinePart. Each column stores its line parts, but there is no need to store line shapes once their lines have been composed.

Columns and line parts have flowboxes (which is are the areas the compositor fits them to) and bounding boxes (which is the area they actually take on the page, including text overhangs). Paragraphs do not have either because a single paragraph can be split across several columns which might end up on different pages. Each paragraph stores a pointer to its first line part.

More about Composition

Here is the reflow process in more detail. Story::CRoot::PartialUpdate() delegates to Story::CScheduler, which decides which story and layout to work on next. It then passes control to the layout's Story::CCompositor. The input to the composition process is a paragraph and a column. The output is a series of Story::CLinePart objects added to the column. The CLineParts contain the information needed to render the text, and to deal with issues like converting mouse coordinates into logical positions.

Story::CCompositor works on one paragraph at a time. It starts by asking a Story::CFieldExpander to copy the entire paragraph into a single, long Story::CLinePart. CFieldExpander is a kind of Story::CGlyphSink. You can change the object used by calling Story::CLayout::SetFieldExpander(), and there-by substitute your own subclass. In this way you can filter the glyphs and glyph attributes as they are copied, for example to control whether powerfields are expanded or not, or to limit the range of font sizes in non-WYSIWYG views.

The compositor then sets up an initial Story::CLineShape. This is the area the line is made to fit. It is made out of rectangles, all of which are the same height (which is the height of the line). Each rectangle is actually a Story::CLinePartBox, and we will end up with one CLinePart object for each CLinePartBox in the CLineShape.

Initially the line shape is set to a single CLinePartBox which is the whole of the current column's width and its remaining depth, less various paragraph indents, "space above" and so forth. This is the upper bound of the space available to the line. We then make a trial wrap to this box. This gives us an estimate of the line's height, so we now have a long, thin box. We then subtract away the wrap shapes.

The wrap shapes (Story::CWrapShape) are objects created by the application and attached to each column. They come in various types and flavours. The text can be forced inside them, or outside them, and they can be plain rectangles or arbitrary polypolygons. When applied to a Story::CLineShape, their effect is to turn the single long CLinePartBox into several shorter boxes. The gaps between boxes are "avoid areas" where text cannot go.

We wrap the line again against the new line shape. This is where the several CLineParts come from. Wrapping is a matter of adding up with widths of all the glyphs in the line and stopping when the total is bigger than the box we're fitting to. Then we have to back-track a little and do something about hyphenation, and finally create a new line part to hold the glyphs which didn't fit. These will be wrapped against the next line part box.

The completed lines are added to the column. The column stores them linearly; it doesn't care whether the parts go side by side or one under the other. When we have filled all the line part boxes from a given line, we know the line's real height, which is the maximum of the heights of all the line parts. We dock this height from the column's remaining depth. Then, if there are any glyphs left over we continue with a new line with those.

See also Composition Classes, Layout Overview.


Serif Story Documentation.
This content last built on 30 Oct 2003.