NOTE: This feature was merged into trunk on 24 October 2012 in bug #54041. See https://issues.apache.org/bugzilla/show_bug.cgi?id=54041 for details.
NOTE: Sample syntax can be found here: http://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_RoundedCorners/examples/fo/advanced/rounded-corners.fo
This page discusses if and how support for rounded borders in FOP could be added.
The XSL-FO specification
XSL 1.1 doesn't contain support for rounded borders. However, the topic appears in the requirements document of XSL-FO 2.0: http://www.w3.org/TR/2008/WD-xslfo20-req-20080326/#N67092
The CSS3 specification
XSL-FO borrows heavily from CSS (CSS2, actually). The current CSS3 working drafts contains a module (called "Backgrounds and Borders") that discuss rounded borders: http://www.w3.org/TR/css3-background/#the-border-radius
A possible extension for rounded borders
It makes sense to look at CSS3 for the naming and semantics of a rounded border feature in FOP since it can be expected that the XSL working group will orient themselves at CSS3 for this once (and if) this finds its way into XSL-FO.
CSS3 defines the following properties: border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-top-left-radius, one for each border edge. The shorthand (border-radius) lets you define all four borders in one property. As with other shorthand, this would be mapped to the four basic properties. Since rounded borders are not currently part of XSL-FO, the properties need to be prefixed with out "fox:" prefix.
Note: Even if you don't specify a border width, border-*-radius is still used to achieve rounded area backgrounds or clip a background image.
To keep it simpler, FOP should ignore rounded borders on inner border edges when the collapsing border model is active. The user can still achieve rounded inner border edges on a table but he has to switch to separate border model.
Looking at various way to create a table with rounded corners [1]:
http://people.apache.org/~jeremias/fop/rounded-borders-table1.png
- easily done with the separate border model.
- easily done with the separate border model.
- separate border model if the second row doesn't have a border-before.
- not doable (which would be the desired fix for 3)
- easily done even with collapsing border model as only the other border segments have rounded borders.
CSS3 doesn't seem to be saying anything of the effect of a rounded border on the padding rectangle. The text actually suggests that the padding rectangle is being clipped. So the user would be responsible to specifying enough padding so text does not get clipped at the border line.
Implementation considerations
Obviously, the FO tree needs to be enhanced with the extension properties and the shorthand.
If the above assumption is correct and CSS3 doesn't expect the user agent to automatically adjust the padding rectangle according to the border-radius properties, then there's no special consideration needed in either the FO tree or the layout engine which makes the whole thing easier. Only the layout managers need to transport the border-radius information to the area tree.
The area tree needs to be extended to carry the border-radius properties. These will simply be additional traits.
To keep implementation effort down, the old renderers will not be extended with this functionality. Only the IFRenderer is taught to transform the area tree traits into the intermediate format.
The intermediate format needs to be extended to accomodate the optional border-radius information, for all of:
- border-rect
- rect
- clip-rect
Finally, the IFPainter implementations have to implement the actualy functionality for each output format.
Difficulties
In general, painting rounded borders and rectangles in PDF, PostScript, SVG and Java2D are not a problem if you figure out how to calculate the starting and ending coordinates of border segments. This is especially important when adjacent border segments have different color. However the CSS3 spec recommends (but doesn't require) that gradients shall be used when rounded borders are specified. This would make the calculation of starting points inside the curve obsolete but require additional effort to achieve the gradient. A gradient will make the output files (PDF and PS only) slightly larger and more complicated (slower) to paint by the viewer/RIP.
http://people.apache.org/~jeremias/fop/rounded-borders.png
Border painting for the above 4 formats would have to be changed to use shapes instead of lines to achieve the gradual adjustment from one border width to the other. That exact point is actually a major difficulty when painting the border styles "dashed" and "dotted". We can no longer use the dash and line-cap features of [BasicStroke]. We'd have to calculate the shape, size and position of all individual dots or dashes. Probably not an easy and fast thing. Also CSS3 doesn't really say how "groove", "ridge", "inset" and "outset" would look like in the rounded case. At any rate, border painting code complexity will increase quite a bit. [2]
Even more complicated are output formats that don't support sophisticated painting operations as the above three. AFP and PCL both don't.
AFP doesn't handle clipping and it paints filled rectangles and border lines (solid only) using PTOCA instructions. This way, borders and rectangles are unproblematic on various printing environments. AFP would support to paint rounded borders using GOCA by actually painting shapes, not lines. However, not all AFP users want to (or can) use GOCA due to target environment limitations and interoperability issues. Furthermore, the borders will be painted for each page separately which AFP purist want to avoid (topic: page segments. More on that below).
A solution for both PCL and AFP would be to generate the borders and backgrounds as bitmap images when a border radius is given. For PCL, this would be yet an additional argument to do all the page content as bitmap, turning the PCL renderer into simple converter that puts a full-page bitmap into a PCL wrapper. Of course, that would require fixing the current performance problem concerning fonts in Java2D.
AFP purists will not accept the size and performance penalty of having such bitmaps inlined. A solution out of this would be to try to reuse the bitmaps produced by identifying recurring border rectangles in a cache and putting the bitmaps in page segments on the document level. It is reasonable to expect that the number of distinctive border rectangle in a print stream is relatively low for the kinds of documents being thrown at the AFP painter. However, it is not clear if an exact (pixel precision) positioning can be guaranteed as FOP uses millipoints internally, not pixels, and rounding differences could occur. Proprietary, programmable layouters working on the pixel level have an advantage here.
PCL doesn't support clipping at all, especially not to shapes that are not rectangles. AFP does have limited support to emulate clipping to a rectangle, but not arbitrary shapes.
Working Implementation
I (PeterHancock) have begun implementing rounded borders privately and recently published a patch to bugzilla#49913. In this implementation I have used the following fox attributes for fine-grain corner specification: for the adjacent borders (BLOCK, INLINE) in {(before,start), (before,end), (after,start), (after,end)}
fox:border-BLOCK-radius-INLINE
is the radius of the corner ellipse in the Block Progression Direction and
fox:border-INLINE-radius-BLOCK
is the radius of the corner ellipse in the Inline Progression Direction.
This differs from the css style where both radii would be specified in an attribute something like fox:border-BLOCK-INLINE-radius="bpd [ipd]"
More detail can be found in fox_exts_and_design_decisions
TODO The attached document should be merged into this wiki page: fox_exts_and_design_decisions
Random Notes
- This feature could be used as occasion to fix the mark layering that was discovered some time ago.
- Fixing mark layering would also allow (to a certain degree) to optimize border painting (i.e. to combine border segments in tables to reduce anti-aliasing artifacts of document viewers). But this is really unrelated to the topic at hand.
[1] These are just a few different variants. Maybe there are more. If anyone knows an additional variant that is missing here, please let me know. (JeremiasMaerki)
[2] I haven't checked any CSS3 implementations or other FO implementations, yet, to see how they do things. (JeremiasMaerki)