| 1 |
lars |
1 |
<html>
|
|
|
2 |
<head>
|
|
|
3 |
<title>Page breaking algorithm</title>
|
|
|
4 |
<link rel="stylesheet" type="text/css" medial="all" title="Default" href="css/help.css"/>
|
|
|
5 |
</head>
|
|
|
6 |
<body>
|
|
|
7 |
|
|
|
8 |
<h1>Page breaking algorithm</h1>
|
|
|
9 |
<p>
|
|
|
10 |
First of all, keep in mind that "smart" page breaking algorithm is available in 2.0 branch since 2.0.9; there's no reason
|
|
|
11 |
to use 2.1 experimental versions, as <b>all</b> features were ported. The difference between 2.1 and 2.0 is, in particular,
|
|
|
12 |
in the following: 2.1 has smart page breaks enabled by default, while 2.0 uses it only if 'smartpagebreak' setting is set to true.
|
|
|
13 |
If you're calling 'configure' when initializing pipeline, you notice no difference, as it will be enabled by default.
|
|
|
14 |
If you're not using 'configure' call ($g_config is set up manually) you should explicitly set 'smartpagebreak' element in your $g_config to 'true'.
|
|
|
15 |
</p>
|
|
|
16 |
|
|
|
17 |
<p>
|
|
|
18 |
To find the exact position of the next page break, script calculates a penalty (a badness, if you prefer) of every possible page break position, and
|
|
|
19 |
selects one with the minimal penalty value. Possible break positions are horizontal lines between line and block-level boxes; inside tables they're horizontal row boundaries and horizontal
|
|
|
20 |
lines passing between line boxes in all table cells in a row (thus, if you're using different font sizes or aligments in different cells, there's
|
|
|
21 |
a big chance there won't be suitable page break places inside this row at all).
|
|
|
22 |
</p>
|
|
|
23 |
|
|
|
24 |
<p>
|
|
|
25 |
Penalty is assigned for the following:
|
|
|
26 |
<table>
|
|
|
27 |
<tr>
|
|
|
28 |
<td>breaking the 'page-break-inside: avoid' rule</td>
|
|
|
29 |
<td>PAGE_BREAK_INSIDE_AVOID_PENALTY</td>
|
|
|
30 |
</tr>
|
|
|
31 |
<tr>
|
|
|
32 |
<td>breaking the 'page-break-after: avoid' rule</td>
|
|
|
33 |
<td>PAGE_BREAK_AFTER_AVOID_PENALTY</td>
|
|
|
34 |
</tr>
|
|
|
35 |
<tr>
|
|
|
36 |
<td>breaking the 'page-break-before: avoid' rule</td>
|
|
|
37 |
<td>PAGE_BREAK_BEFORE_AVOID_PENALTY</td>
|
|
|
38 |
</tr>
|
|
|
39 |
<tr>
|
|
|
40 |
<td>leaving less than 'orphans' lines on the next page</td>
|
|
|
41 |
<td>PAGE_BREAK_ORPHANS_PENALTY</td>
|
|
|
42 |
</tr>
|
|
|
43 |
<tr>
|
|
|
44 |
<td>leaving less than 'widows' lines on the next page</td>
|
|
|
45 |
<td>PAGE_BREAK_WIDOWS_PENALTY</td>
|
|
|
46 |
</tr>
|
|
|
47 |
<tr>
|
|
|
48 |
<td>breaking between line boxes instead of block-level boxes</td>
|
|
|
49 |
<td>PAGE_BREAK_LINE_PENALTY</td>
|
|
|
50 |
</tr>
|
|
|
51 |
<tr>
|
|
|
52 |
<td>breaking inside box having non-zero padding or border</td>
|
|
|
53 |
<td>PAGE_BREAK_BORDER_PENALTY</td>
|
|
|
54 |
</tr>
|
|
|
55 |
</table>
|
|
|
56 |
</p>
|
|
|
57 |
|
|
|
58 |
<p>
|
|
|
59 |
All assigned penalties stack for each positions; after that a "free space" penalty is added. This additional value is
|
|
|
60 |
used to prevent too much free space at the bottom of the page and is calculated using the following rules:
|
|
|
61 |
<pre>
|
|
|
62 |
free space penalty = 0, if distance from the bottom page edge / page height < MAX_UNPENALIZED_FREE_FACTION, or
|
|
|
63 |
free space penalty = MAX_PAGE_BREAK_HEIGHT_PENALTY, if distance from the bottom page edge / page height > MAX_FREE_FACTION, or
|
|
|
64 |
free space penalty = MAX_PAGE_BREAK_HEIGHT_PENALTY * ((distance from the bottom page edge / page height) - MAX_UNPENALIZED_FREE_FRACTION) / (MAX_FREE_FRACTION - MAX_UNPENALIZED_FREE_FRACTION), otherwise
|
|
|
65 |
</pre>
|
|
|
66 |
|
|
|
67 |
<p>After this, script selects the position with the least penalty value and proceeds to the next page.</p>
|
|
|
68 |
|
|
|
69 |
<p>Refer to default.css for the default CSS rules related to page breaking, and to config.inc.php for default values of penalties</p>
|
|
|
70 |
|
|
|
71 |
</body>
|
|
|
72 |
</html>
|