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>
10First of all, keep in mind that &quot;smart&quot; page breaking algorithm is available in 2.0 branch since 2.0.9; there's no reason
11to use 2.1 experimental versions, as <b>all</b> features were ported. The difference between 2.1 and 2.0 is, in particular,
12in the following: 2.1 has smart page breaks enabled by default, while 2.0 uses it only if 'smartpagebreak' setting is set to true.
13If you're calling 'configure' when initializing pipeline, you notice no difference, as it will be enabled by default.
14If 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>
18To 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
19selects 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
20lines 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
21a big chance there won't be suitable page break places inside this row at all).
22</p>
23
24<p>
25Penalty 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>
59All assigned penalties stack for each positions; after that a "free space" penalty is added. This additional value is
60used to prevent too much free space at the bottom of the page and is calculated using the following rules:
61<pre>
62free space penalty = 0, if distance from the bottom page edge / page height < MAX_UNPENALIZED_FREE_FACTION, or
63free space penalty = MAX_PAGE_BREAK_HEIGHT_PENALTY, if distance from the bottom page edge / page height > MAX_FREE_FACTION, or
64free 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>