You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by Apache Wiki <wi...@apache.org> on 2006/08/04 12:53:34 UTC

[Xmlgraphics-fop Wiki] Trivial Update of "GoogleSummerOfCode2006/FloatsImplementationProgress/ImplementingSideFloats" by VincentHennebert

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Xmlgraphics-fop Wiki" for change notification.

The following page has been changed by VincentHennebert:
http://wiki.apache.org/xmlgraphics-fop/GoogleSummerOfCode2006/FloatsImplementationProgress/ImplementingSideFloats

The comment on the change is:
Splitting: 3- Implementing Side-floats

New page:
#pragma section-numbers on

'''Contents'''
[[TableOfContents]]


= Formalizing the Problem =
The specification of side-floats is in part taken from the CSS2 recommendation and adapted to XSL-FO. It may be useful to summarize and reformulate the spec to have a precise understanding of how side-floats should be handled.

An fo:float element with the "float" property set to "start" or "end":
 * generates a ''block-area'' of class "xsl-side-float", which also is a ''reference-area''
 * is placed as a child of the nearest ancestor reference-area of the anchor-area or as a child of a later reference-area of the same chain
 * the length in the inline-progression-direction is the intrisic length of the area
 * border and padding should be set to zero on all edges of the side-float; the space properties don't apply to fo:float; as a consequence, the allocation-rectangle, border-rectangle, padding-rectangle and content-rectangle of a side-float area are the same
 * block-areas before and after the side-float flow in the block-progression-direction as if the float didn't exist. Line-areas are reduced to make room for the float

To formalize the rules of placement of side-floats, we will set up the following coordinate system:
 * the x-axis goes into the inline-progression-direction of the nearest ancestor reference-area;
 * the y-axis goes into the block-progression-direction;
 * the origin is the point of the reference-area's content-rectangle which is at the intersection of the start-edge and before-edge.

In such a coordinate-system, a side-float area is characterized by the (x,y) coordinates of its "start-before point", that is, the point of its allocation-rectangle (or border-rectangle, or padding-rectangle, or content-rectangle) which is at the intersection of the start-edge and before-edge.

http://atvaark.dyndns.org/~vincent/side-floats_coordinate-system.png

== Rules for Placing Side-floats ==
Some definitions:
 * we will call a start-float the block-area generated by an fo:float with "float"="start" or "left". Same for end-float
 * we will note start-float ≺ start-float' if start-float precedes start-float'; that is, the generating fo:float for start-float is before the generating fo:float for start-float' in the fo tree.

The nine rules given in the description of the "float" property may then be reformulated like the following:
 1. for a start-float, x ≥ 0
 for an end-float, x + ipd ≤ ipd,,ref-area,,
 2.#2 ∀ start-float' ≺ start-float, x > x' + ipd' or y > y' + bpd'
 ∀ end-float' ≺ end-float, x + ipd < x' or y > y' + bpd'
 3.#3 ∀ start-float s, ∀ end-float e, [y,,s,,, y,,s,, + bpd,,s,,] ∩ [y,,e,,, y,,e,, + bpd,,e,,] ≠ ∅ ⇒ x,,s,, + ipd,,s,, < x,,e,,
 4. y ≥ 0
 5. ∀ side-float' ≺ side-float, y ≥ y'
 ∀ block-area ≺ side-float, y,,side-float,, ≥ y,,block-area,,, where y,,block-area,, is the y-coordinate of the before-edge of the block-area's border-rectangle minus the block-area's space-before(.optimum?)
 6.#6 ∀ line-area ≺ start-float, y ≥ y[before-edge of the line-area's allocation-rectangle]
 7. ∃ start-float', [y, y + bpd] ∩ [y', y' + bpd'] ≠ ∅ ⇒ x + ipd ≤ ipd,,ref-area,,
 8. y should be minimized
 9. x should be minimized
 10. if "clear" = "left", "start", "both", ∀ start-float' ≺ side-float, y > y' + bpd'
 if "clear" = "right", "end", "both", ∀ end-float' ≺ side-float, y > y' + bpd'

Here's a [http://atvaark.dyndns.org/~vincent/side-floats.pdf pdf version] for those whose browser has difficulties displaying UTF-8 characters.

== Uncertainties ==
At the beginning of section 9.5 of the CSS2 recommendation, it is loosely explained how floats should be placed, and it is said that the precise placement rules should be found in the description of the "float" property.

Two hints are given at this place, of which only one may be retrieved in the precise rules:
 * the top of the floated box is aligned with the top of the current line box: this corresponds to rule 6
 * ... or bottom of the preceding block box if no line box exists.

This last point may occur in XSL-FO if the generated anchor area must be a block-area. AFAICT there is no rule for it in the description of the "float" property. Rule 5 would even let think that the top of the floated box should be aligned with the ''top'' of the previous block box. Moreover, in the CSS 2.1 candidate recommendation this sentence doesn't appear anymore.

That said, I think the behavior that most users would expect is to align the float with the bottom of the previous (non-floating) block box. This also is what is implemented by all the browsers I've tested (Konqueror, Safari, Firefox). So I think we may implement it like that too.

Another uncertainty is caused by the following sentence of section 9.5: "If there isn't enough horizontal room on the current line for the float, it is shifted downward, line by line, until a line has room for it." And what if the height of the float is less than the line-height? Should it still be shifted one entire line downward? This sentence is in contradiction with rule 8 (y should be minimized). In CSS 2.1 it has been rephrased such that "line by line" doesn't appear anymore. So I think we may go with CSS 2.1.

Finally, may side-floats be split on several pages? There is nothing about that in the XSL-FO spec. The chapter 13, "Page Media" of the CSS2 recommendation gives a small hint in section 13.3.6: we should "avoid breaking inside a floated element". If one uses side-floats to have margin notes, one can reasonably expect them to be split on several pages. Therefore, if it is simple enough to implement side-float breaking, I'll do it; if it involves too many changes or a too complicated algorithm, I'll leave it for now (note that Xep does not break side-floats, even if they are too big to fit on a page; they are simply discarded).

== Computing Intrusion-adjustments ==
=== Definitions ===
Unless otherwise noted, the coordinates are those of the "start-before" vertex of the allocation-rectangle.
 * Let A be a side-float, B a block-area with the same nearest ancestor reference-area;
   A, B inline-overlapping ⇔ [y,,A,,, y,,A,, + bpd,,A,,] ∩ [y,,B,,, y,,B,, + border-before,,B,, + padding-before,,B,, + bpd,,B,, + padding-after,,B,, + border-after,,B,,] ≠ ∅
 * Let A be a start-float, B a block-area with the same nearest ancestor reference-area;
   A encroaches-upon B ⇔ A, B inline-overlapping ''and'' start-indent,,B,, < x,,A,, + ipd,,A,,
   Then start-encroachment(A,B) = x,,A,, + ipd,,A,, - start-indent,,B,,
 * Let A be an end-float, B a block-area with the same nearest ancestor reference-area;
   A encroaches-upon B ⇔ A, B inline-overlapping ''and'' end-indent,,B,, < ipd,,A,, + end-indent,,A,,
   Then end-encroachment(A,B) = ipd,,A,, + end-indent,,A,, - end-indent,,B,, = ipd,,ref-area,, - x,,A,, - end-indent,,B,,

=== Computation Rules ===
Let F be a formatting object to which the "intrusion-displace" property applies. Then:
 * if intrusion-displace = "none"
   start-intrusion-adjustment = end-intrusion-adjustment = 0

 * if intrusion-displace = "line"
  * for each generated block-area B which is not a line-area:
  ||<|2>local-start-intrusion-adjustment =||0 if parent-area = ref-area||
  ||start-intrusion-adjustment of parent-area, else||
  Then start-intrusion-adjustment,,B,, = max(local-start-intrusion-adjustment,,B',,, B' normal block-area generated and returned by F)
  * for each generated line-area L
  ||<|2>start-intrusion-adjustment = max||start-intrusion-adjustment(L parent)||
  ||start-encroachment(A,L), A start-float such that A encroaches-upon L||

 * if intrusion-displace="indent"
  * for each generated block-area B which is not a line-area:
  ||<|2>local-start-intrusion-adjustment =||0 if parent-area = ref-area||
  ||start-intrusion-adjustment of parent-area, else||
  Then start-intrusion-adjustment,,B,, = max(local-start-intrusion-adjustment,,B',,, B' normal block-area generated and returned by F)
  * for each generated line-area L
  ||<|6>start-intrusion-adjustment = max||||<(>start-intrusion-adjustment(L parent)||
  ||start-encroachment(A,L)||||<(>A start-float such that A encroaches-upon L||
  ||<|4>start-encroachment(A,B')||A start-float such that A,L inline-overlapping||
  ||B' block-area ancestor of L||
  ||B' descendant of L nearest ancestor ref-area||
  ||∃ L' line-area child of B', A encroaches-upon L'||

 * if intrusion-displace="block"
  * for each generated block-area B which is not a line-area:
  ||<|9>local-start-intrusion-adjustment = max||||<(>0||
  ||start-intrusion-adjustment(B parent)||B parent is not a ref-area||
  ||<|3(>start-encroachment(A,B)||A start-float||
  ||generating-fo(A) is not a descendant of F||
  ||∃ L' line-area child of B, A encroaches-upon L'||
  ||<|4(>start-encroachment(A,B')||A start-float such that A,B inline-overlapping||
  ||B' block-area ancestor of B||
  ||B' descendant of B nearest ancestor ref-area||
  ||∃ L line-area child of B', A encroaches-upon L||
  Then start-intrusion-adjustment,,B,, = max(local-start-intrusion-adjustment,,B',,, B' normal block-area generated and returned by F)
  * for each generated line-area L
  ||<|2>start-intrusion-adjustment = max||start-intrusion-adjustment(L parent)||
  ||start-encroachment(A,L), A start-float such that A encroaches-upon L||

I'll first implement the "line" value, as this is probably the most expected by users. I'll forget "block" and "indent" for now if after a quick look they turn out to be too complicated to implement.

---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org