diff options
Diffstat (limited to 'docs/design/breakpos.xml')
-rw-r--r-- | docs/design/breakpos.xml | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/docs/design/breakpos.xml b/docs/design/breakpos.xml deleted file mode 100644 index 34df68d9f..000000000 --- a/docs/design/breakpos.xml +++ /dev/null @@ -1,289 +0,0 @@ -<?xml version="1.0" standalone="no"?> - -<!-- Overview --> - -<document> - <header> - <title>Layout Managers</title> - <subtitle>Break Possibility Proposal</subtitle> - <authors> - <person name="Karen Lease" email="klease@club-internet.fr"/> - </authors> - </header> - - <body> -<s1 title="Introduction"> -<p> -As explained in <link href="layout.html">Layout</link>, -the hierarchy of Layout Managers is responsible for building and placing -areas. Each Layout Manager is responsible for creating and filling -areas of a particular type, either inline or block. This document -explains one potential algorithm for this process. It is based on the -the generation of <em>break possibilities</em> (BP for short). The -Layout Managers (LM for short), will generate one or more BP and -choose the best one. The BP is then used to generate the corresponding -areas. -</p> -</s1><s1 title="Anatomy of a Break Possibility"> -<p>A break possibility is represented by the BreakPoss class. A -BreakPoss contains size information in the stacking direction and in -the -non-stacking direction (at least for inline areas, it must have both). Flags -indicating various conditions (ISFIRST, ISLAST, CAN_BREAK_AFTER, -FORCE_BREAK_AFTER, ANCHORS etc). A BreakPoss contains a reference to -the top-level LayoutManager which generated it. -</p> -<p>A BreakPoss contains an object implementing -the BreakPoss.Position interface. This object is specific to the layout -manager which created the BreakPoss. It should indicate where the -break occurs and allow the LM to -create an area corresponding to the BP. A higher level LM Position -must somehow reference or wrap the Position returned by its child LM in its -BreakPoss object. The layout manager modifies the flags and dimension -information in the BP to reflect its own requirements. For example an -inline FO layout manager might add space-start, space-end, border and -padding values to the stacking or non-stacking dimensions. It might also -modify the flags based its on keep properties.</p> -</s1> -<s1 title="Turning Break Possibilities into Areas"> -<p>Once break possibilities have been generated, the galley-level -layout manager selects the best one -and passes it back to the LayoutManager which generated it to create -the area. A LayoutManager is responsible for -storing enough information in its Position objects to be able to -create the corresponding areas.</p> - </s1> -<s1 title="A walk-through"> -<p>Layout Managers are created from the top down. First the -page sequence creates a PageLM and a FlowLM. The PageLM will manage -finding the right page model (with help from the PageSequenceMaster) -and managing the balancing act between before-floats, footnotes and -the normal text flow. The FlowLM will -manage the normal content in the main flow. We can think of it as a -<em>galley</em> manager. -</p> -<p>In general, each LM asks its child LMs to return sucessive -break possibilities. It passes some -information to the child in a flags object and it gets back -a break possibility which contains the size in -the stacking direction as well as information about such things as -anchors, break conditions and span conditions which can change the -reference area environment. This process continues down to the lowest -level of the layout manager hierarchy which corresponds to atomic -inline-level FOs such as characters or graphics. -</p> -<p> -Each layout manager will repeatedly call getNextBreakPoss on its current -child LM until the child returns a BP with the ISLAST -flag set. Then the layout manager moves on to its next child LM (ie, -it asks the next child FO to generate a layout manager.) Galley level -layout managers which are Line and Flow will return to their parent -layout managers either when they have finished their content or when -they encounter a a BP which will fill one of their areas. -</p> -<p>The break possibilities are generated from the bottom up. -All inline content must first be broken into -lines which are then stacked into block areas. This is done by the -LineLayoutManager, which creates line areas. -The LineLM asks its child LM to generate a break possibility, which -represents a place where the line can end. This -initially means each potential line-end (primarily spaces or forced -linefeeds and a few other potential line-end characters such as hard -hyphens.) The text LM returns an object which stores the size in the -stacking direction as a MinOptMax triplet -and a <em>cost</em>, which is based on how well this break -would satisfy the constraints. The Text LM keeps track of its position in -the text content and returns the total size of the text area it would -create if it were to break at a given point. The returned BP -object also contains information about whether the break is forced -(linefeed) or whether this is the last area which can be generated by -the LM (ISLAST flag). If a textFO ends on a non-break character, the -ISLAST flag is set, but the CAN_BREAK_AFTER flag isn't, since we don't -know if there is any following text in another inline object for -example. -</p> -<p>Variable size content is taken into account from -the bottom up. Each LM returns a range of sizes in the stacking -direction, based on property values. For text, this comes from -variable word-space values or letter-space values. For other inline -objects, it may include variable space-start and space-end values -(after calculation of the entire sequence of space specifiers at a -particular break possibility.)</p> -<p>The main constraint for laying out -lines is the available inline-progression-dimension (IPD) for the line -area to be created. This -depends on the IPD of the reference area ancestor, on the indents of the -containing fo:block, and on any side-floats which may be intruding on -this line.</p> -<note>See below <link href="#getRefIPD">Getting the Reference -IPD</link> -for discussion of how the reference area IPD is -transmitted to the Line LM.</note> -<p>For now, let's assume that only the LineLM knows about the IPD -available to it. Therefore only it can make a decision about which BP -is the best one; the lower level inline layout managers can only -return potential break points.</p> -<note>There are certainly optimizations to this model which can be -examined later.</note> -<p>So the Line LM will ask its child LM(s) for break possibilities until -it gets back a BP whose stacking dimension <em>could</em> fill the -line. This means that the BP.stackdim.max >= LineIPD.min. It can look -for further BP, perhaps one whose stackdim.opt is closer to the -LineIPD.opt. If it isn't happy with the choice of break possibilities, -it can go past the end of the line to the next one, and then try to -find a hyphenation point between the last one which fits and the first -one which doesn't. If no possibility is found whose min/max values -enclose the available IPD, some constraint will be violated (and -reported in the log.) The actual strategy is up to the Line LM and -should be able to be easily replaced without changing the architecture -(Strategy pattern). -</p> -<p>The definition of a good break possibility depends on the -properties at the block and inline level which govern things such as -wrapping behavior and justification mode. For example, if lines are -not to be wrapped, only an explicit linefeed can serve as a BP. If -lines are wrapped but not justified then there is no requirement to -completely fill the IPD on each line, but a sophisticated layout -manager will try to achieve "aesthetic rag". -</p> -<p>Note that no areas have actually been created yet. Once the LineLM -has found a potential break point for the inline content, it can -calculate the total size of the line area which would be created. The -size in the IPD is determined by the Line LM based on the chosen BP. -The size of the line area in the the block-progression-dimension -depends on the size of the text (or other inline content). These -values are set by the inline-level LM -in their returned BP (in terms of ascender and descender heights with -respect to the baseline). The LineLM adds spacing implied by the -current line-stacking strategy and line-height property values. It -stores a reference to the chosen inline BP and "wraps" that in its own -Position object which it stores in the BP it returns to its parent LM -(the block layout manager). -</p><p>The block LM now has a potential break position after its -first line. It assigns that possibility a cost, based on widow, orphan -and keep properties. It can also calculate the total size of the block -area it would create, were it to end the area after this line. It does -this by adding any padding and border (taking into account -conditionality). It also calculates space-before and space-after -values, or contributes to building up a sequence of such values. -With this information, the block LM creates a new BP (or -updates the existing one). It stores a Position object in this -BP which wraps the returned BP from its child Line LM. -It returns the new BP to its parent and so on, back up to the -FlowLM.</p> -<p>Obviously there is more complicated logic involved when dealing -with lists and tables. These cases need to be walked through in detail.</p> -<p>The FlowLM sees if the returned stacking dimension will still -fit in its available block-progression-dimension (BPD). It repeatedly calls -getNextBreakPoss on its -child LMs until it reaches the maximum BPD for the flow reference area -or until there is no more content to lay out. If one child LM is -finished, it moves on to the next until the last child LM has returned -a BP with the ISLAST flag set. If any child LM returns a -BP with a FORCE_BREAK_BEFORE or SPAN flag set, the FlowLM will -force layout of any pending break possibilities and return to its -parent (the PageLM) in order to handle the break or span condition.</p> -<p>If the returned BP has any new before-float or footnote anchors in -it (ANCHOR flag in the -BP), the FlowLM will also return to the PageLM. The PageLM must then -try to find space to place the floats, possibly asking the FlowLM for -help if the body contains multiple columns.</p> -</s1> -<s1 title="Some issues"> -<p>Following are a few remarks on specific issues.</p> -<s2 title="Where Line Layout Managers are created"> -<p>If the first child FO in a block FO is an inline-level FO -such as text, the block LM creates an intermediate level LineLM -to layout the -sequence of inline content into Lines. Note that the whole sequence of -inline FOs is managed by a single instance of LineLM. The LineLM -becomes the parent to the various inline-level LM created by each -individual inline FO. -Since an fo:block can have both block and inline content, its LM -may create a sequence of intermixed BlockLM and LineLM.</p> -</s2> -<anchor id="getRefIPD"/><s2 title="Getting the reference IPD"> -<p>When the layout process starts, with the FlowLM asking its first -child LM for a break possibility, the IPD isn't known, since we don't -know whether -the first FO might be spanning, or on which page it might start. (Of -course, if all page masters in the sequence have the same region-body IPD -and all have only a single column, the IPD will never change -and could already be calculated before starting layout.) -The FlowLM gets its -first child LM and calls its getNextBreakPoss method. That is a child LM for -some block-level FO. For now, suppose it's an fo:block. The BlockLM -will create its first child LM, which may be another block-level LM in -the case of nested blocks or a LineLM as explained above. (Question: -do we need a START flag for layout status?) -</p> -<p>We keep calling getNextBreakPoss on lower level layout managers until we -get down to the inline level or to a level which cannot have break-before -properties, such as a list-item-label. At that point, we assume we are -going to have to layout some actual content. But we can't do that yet -since we don't know the inline-progression-dimension. So we return a -BP object which has 0 size in the stacking dimension, but which -has flags set to signal to -higher-level layout managers what needs to be done. If it has a break-before -property or a span property, it stores these in the BP. If -no reference IPD is yet defined, it sets a flag to get that. It then -returns to its parent. The parent LM will inspect the BP object -returned. In general, it "wraps" it with information about its own -needs. If the returned BP is not actually returning any potential -areas, the LM can still add information about its own break or span -requirements. This return path continues back up to the PageLM. It -will then check break and span requirements and create a new page -if necessary using the appropriate page-master. At that point, the -reference IPD for the main -flow is known and is set in the flags object used for -the next getNextBreakPoss call to the lower level LM. -</p><p>Using this information, the BlockLM parent can now calculate -the available IPD for its LineLM child, based on its indents. -(If there are any -side-floats information about the intrusion must be passed down by the -FlowLM to lower level managers.) The LineLM can now generate a series -of BreakPoss objects, which it passes back to its parent LM. -</p> -</s2> -<s2 title="Hyphenation"> -<p> -The LineLM is responsible for initiating hyphenation if it is allowed -by the properties and if no satisfactory BP can be found without -hyphenating. The hyphenation manager is passed two break -possibilities, one whose IPD is less than the desired line area IPD -and one whose IPD is greater. These break possibilities might have -been generated by different inline-level layout managers (text + a -wrapper with a color change for example), though -frequently they represent two positions in a single text run. -If hyphenation is successful, a new BP is -returned. The LineLM may look for several intermediate BP -based on the "cost" of the returned possibilities. If no intermediate -BP is found, the line will be "short", the white-space stretch will be -exceeded, or perhaps the content will be overflowed or clipped, -depending on various property settings.</p> -</s2> -<s2 title="Optimizing"> -<p>It obviously seems inefficient to go down to the lowest level -LM and back up to the FlowLM for every possible line-break -decision. It seems like it would be possible to optimize by letting -the lower level layout managers run until they had exceeded the -current limit in -the stacking direction. They would then return control to the "galley" -level (LineLM or FlowLM) which would fine-tune the break decision by -asking the lower level LM to find a previous BP which would fit. At -the inline level, this means hyphenation as described above.</p> -<p>Another interesting question is at what point pending break -possibilities can be turned into areas.The idea is to wait until we -are sure we won't have to redo the breaking. This depends on the -sophistication of the layout strategy. For example, if a -linebreak can be considered final if the line is full and there are no -anchors on the line, we could create the LineArea at that point. But -if we are willing to change a previous line-end decision to get a -better overall composition of a whole group of lines (to prevent multiple -hyphens for example), we might wait until the LineLM had finished -laying out all its material and then make all the Lines at once.</p> -</s2> -</s1> - </body> -</document> - |