Hey all,
I found a strange issue with the layouting algorithm of inline boxes:
When using certain combinations of font-sizes, line-heights and top
margins on a <h1> containing a <span>, the span is partly positioned on
the previous page.
Consider this example (full HTML and PDF attached):
<html xmlns="
http://www.w3.org/1999/xhtml">
<head>
<style type="text/css" media="print">
@page {
@bottom-right {
content: counter(page);
}
}
h1 {
background-color: blue;
font-family: sans-serif;
font-size: 38pt;
line-height: 40pt;
margin-top: 0;
}
h1 span {
/*display: inline-block; Toggle this to fix the issue */
background-color: lime;
}
a:after {
content: " (see page " target-counter(attr(href), page) ")";
}
</style>
</head>
<body>
<div style="page-break-before: always;">
<h1 id="h"><span id="s">the heading</span></h1>
<a href="#h">link to heading</a>
<a href="#s">link to span</a>
</div>
</body>
</html>
I force a page break at the start to show the issue. With the span
having display:inline; the span starts on page 1 whereas its containing
h1 starts on the second page, the two links demonstrate this. When you
switch the span to display:inline-block it is placed correctly.
I've traced it down to
org.xhtmlrenderer.layout.InlineBoxing#alignInlineContent (line 679)
where a negative value is set using box.setY(). This results in the
<span>'s InlineBox having an absY value lesser than that of the
surrounding <h1> box.
I think the getInitialMeasurements() methods behaves a bit weird in this
case:
float lineHeight = container.getStyle().getLineHeight(c);
int halfLeading = Math.round((lineHeight -
container.getStyle().getFont(c).size) / 2);
if (halfLeading > 0) {
halfLeading = Math.round((lineHeight -
(strutM.getDescent() + strutM.getAscent())) / 2);
}
After the first assignment halfLeading seems to have a reasonable value
> 0, however after the second assignment it has a negative value
(depending on configured font-size and line-height).
To me it seems as if the values in strutM do not consider the correct
font-size. At least a negative halfLeading doesn't make any sense to me,
but I might be missing something here.
Do you have any ideas on how to properly fix this?
Thanks,
Jens