The prototype demonstrates that a separate system of managers is unnecessary. Managers _were_ used in the prototype, and worked well, but the FO to manager relationship is 1:1.
An FO may fall into the following categories:
If FOs generate areas they may be differentiated further by the types of areas that they generate (? means 0 or 1, * is infinity):
Refer to the properties document for detailed information.
All formatting objects will ultimately extend an foFormattingObject base class. This class will be responsible for property inheritance, and mapping of corresponding properties (absolute <-> relative). All formatting objects share this functionality.
Formatting objects will maintain a list of properties that apply to them specifically.
The prototype demonstrates that if a manager approach is adopted, that because of the differences outlined in para 2, coupled with the extensive variability of properties across FOs and their subsequent effects, that one ends up with almost as many different kinds of managers as there are FOs. This argues for keeping layout logic in each FO - certainly from a model standpoint this is easily justified.
There is a substantial amount of layout logic that can be placed in the foFormattingObject class. It will comprise a number of different functions - the point is that no one single layout function can serve more than a few FOs, let alone all of them. So it is unlikely that there will be extra levels of inheritance between foFormattingObject and the actual formatting object classes.
Runs of text (PCDATA) will become special formatting objects in their own right. An unbroken run of PCDATA in the FO should appear to the formatter core as a formatting object with properties as specified by fo:character, influenced by the parent (real) FO.
Here is a brief summary of the lifecycle of a formatting object:
check the parent content model to see if this element can be added in this position
Rationale: it is impossible to completely express the FO tree relationships with XML DTDs, and very difficult to do so with schemas (probably also not possible), because they use references to _descendants_.
NOTE (EB): in SGML there was the "exclusion operator" which was able to express such conditions. "-(float)" was a way to write you didn't want to see "float" elements at any level below. I don't know if this is still possible with XML, and if yes, whether they used it in the FO DTD or not. I suggest to do at least a test, because it's useless to do such tests if the validating parser can do them for you.
NOTE (CS): Created a xsd schema for basic validation of content. the relationships above are not described, so those constraints must be done through code. Extension elements in other namespaces not supported yet. Due to "any property can be present on any fo" interpretation of the spec (http://lists.w3.org/Archives/Public/xsl-editors/2004JanMar/0021.html) the attributes are restricted as follows:
dimension the current area from 1) using dimensions (remaining space in the stacking direction, especially) from the _parent_ reference area, the allocation rectangle for this area (as determined by properties on this FO; Section 4.2.3 in the XSL spec), and the stacking constraints between this area and the preceding one (e.g resolved spaces).
This dimensioned area may have a fixed size in both dimensions, or, as is more often the case, may have a zero current size in one dimension, with a known maximum value.
The area, once dimensioned, will have a block-progression-direction and an inline-progression-direction, a current and a maximum dimension in the block-progression-direction, and a current and maximum dimension in the inline-progression-direction.
Operations proceed with child FOs of this FO. According to _their_ layout() methods they will ask this FO for its _current_ reference area (Step 3 in viii above), and will also ask this FO for available space. If space is available this FO will furnish dimensions, but it will _not_ make any adjustments to the dimensions of its current area yet.
If space is _not_ available (e.g. a line area will not fit into the current block area) then we do exactly viii/2 above. This causes layout() to be called on all ancestors up to page-sequence level, hence re-creating new areas as required, in a new column and/or page. The current area for this FO will change. Immediately prior to actually calling newPage() or newColumn() we call finish_area() on this FO (see (c) below)).
NOTE: the primary reason why more generic managers will not work well is because there are numerous constraints that vary from FO to FO. It is when a child FO is being added to an FO that the parent must satisfy these extra constraints (e.g special rules for tables, lists).Further discussion: this sequence of operations (in particular, child areas are added as late as possible, and parents are only resized at that time) allows us to defer consideration of keeps in detail for now, with reasonable assurance that the required mechanism can be retrofitted. (AHS: I have a decent mental idea of how this would work).
The conceptual area tree produced by the core formatter will be fed to a SVG translator, on a page by page basis, as pages are completed. The formatter must deliver completed pages. The cache is responsible for satisfying the user agent delivery strategy.
The SVG translator will deliver a minimum, adequate subset of SVG. (To be determined). The cache will store these simplified SVG pages. This format will be both an in-memory and on-disk representation.