View | Details | Raw Unified | Return to bug 44328
Collapse All | Expand All

(-)test/layoutengine/standard-testcases/block_table_orphans_widows.xml (+119 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
  Licensed to the Apache Software Foundation (ASF) under one or more
4
  contributor license agreements.  See the NOTICE file distributed with
5
  this work for additional information regarding copyright ownership.
6
  The ASF licenses this file to You under the Apache License, Version 2.0
7
  (the "License"); you may not use this file except in compliance with
8
  the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
  Unless required by applicable law or agreed to in writing, software
13
  distributed under the License is distributed on an "AS IS" BASIS,
14
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
  See the License for the specific language governing permissions and
16
  limitations under the License.
17
-->
18
<!-- $Id$ -->
19
<testcase>
20
  <info>
21
    <p>
22
      This test checks the behavior of the "orphans" and "widows" properties
23
      in case tables are nested in blocks.
24
    </p>
25
  </info>
26
  <fo>
27
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
28
      <fo:layout-master-set>
29
        <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in">
30
          <fo:region-body />
31
        </fo:simple-page-master>
32
      </fo:layout-master-set>
33
      <fo:page-sequence master-reference="normal">
34
        <fo:flow flow-name="xsl-region-body">
35
          <fo:block id="block-1">
36
            <!-- Check that the last row is not unnecessarily kept together.
37
                 The inner block's widows constraint causes the table-layout code
38
                 to generate a merged last box, which as a single box, satisfies 
39
                 the containing block's constraint.
40
              -->
41
            <fo:table table-layout="fixed" width="100%">
42
              <fo:table-column column-width="proportional-column-width(1)" />
43
              <fo:table-body>
44
                <fo:table-cell starts-row="true" ends-row="true">
45
                  <fo:block>
46
                  Lorem ipsum dolor sit amet, consectetur
47
                  adipiscing elit. Cras placerat, lectus vel
48
                  iaculis euismod, ipsum enim dapibus
49
                  urna, eu pellentesque velit dolor ac 
50
                  </fo:block>
51
                </fo:table-cell>
52
                <fo:table-cell starts-row="true" ends-row="true">
53
                  <fo:block>
54
                  purus. Maecenas vitae pulvinar turpis.
55
                  Duis venenatis tincidunt velit, fringilla
56
                  dignissim sapien faucibus vel. Quisque
57
                  placerat ornare consectetur. Aenean
58
                  </fo:block>
59
                </fo:table-cell>
60
                <fo:table-cell starts-row="true" ends-row="true">
61
                  <fo:block>
62
                  Lorem ipsum dolor sit amet, consectetur
63
                  adipiscing elit. Cras placerat, lectus vel
64
                  iaculis euismod, ipsum enim dapibus
65
                  urna, eu pellentesque velit dolor ac 
66
                  </fo:block>
67
                </fo:table-cell>
68
              </fo:table-body>
69
            </fo:table>
70
          </fo:block>
71
          <fo:block id="block-2" break-before="page">
72
            <!-- Check that the first row is not unnecessarily kept together.
73
                 The inner block's orphans constraint causes the table-layout code
74
                 to generate a merged first box, which as a single box, satisfies 
75
                 the containing block's constraint.
76
              -->
77
            Lorem ipsum dolor sit amet, consectetur
78
            adipiscing elit. Cras placerat, lectus vel
79
            iaculis euismod, ipsum enim dapibus
80
            urna, eu pellentesque velit dolor ac 
81
            purus. Maecenas vitae pulvinar turpis.
82
            Duis venenatis tincidunt velit, fringilla
83
            dignissim sapien faucibus vel. Quisque
84
            placerat ornare consectetur. Aenean
85
            <fo:block id="block-2a">
86
              <fo:table table-layout="fixed" width="100%">
87
                <fo:table-column column-width="proportional-column-width(1)" />
88
                <fo:table-body>
89
                  <fo:table-cell starts-row="true" ends-row="true">
90
                    <fo:block>
91
                    Lorem ipsum dolor sit amet, consectetur
92
                    adipiscing elit. Cras placerat, lectus vel
93
                    iaculis euismod, ipsum enim dapibus
94
                    urna, eu pellentesque velit dolor ac 
95
                    </fo:block>
96
                  </fo:table-cell>
97
                  <fo:table-cell starts-row="true" ends-row="true">
98
                    <fo:block>
99
                    purus. Maecenas vitae pulvinar turpis.
100
                    Duis venenatis tincidunt velit, fringilla
101
                    dignissim sapien faucibus vel. Quisque
102
                    placerat ornare consectetur. Aenean
103
                    </fo:block>
104
                  </fo:table-cell>
105
                </fo:table-body>
106
              </fo:table>
107
            </fo:block>
108
          </fo:block>
109
        </fo:flow>
110
      </fo:page-sequence>
111
    </fo:root>
112
  </fo>
113
  <checks>
114
    <eval expected="10" xpath="count((//page)[1]//lineArea)" />
115
    <eval expected="2" xpath="count((//page)[2]//lineArea)" />
116
    <eval expected="10" xpath="count((//page)[3]//lineArea)" />
117
    <eval expected="6" xpath="count((//page)[4]//lineArea)" />
118
  </checks>
119
</testcase>
(-)test/layoutengine/standard-testcases/widows-orphans_keep-with-next.xml (+66 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
  Licensed to the Apache Software Foundation (ASF) under one or more
4
  contributor license agreements.  See the NOTICE file distributed with
5
  this work for additional information regarding copyright ownership.
6
  The ASF licenses this file to You under the Apache License, Version 2.0
7
  (the "License"); you may not use this file except in compliance with
8
  the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
  Unless required by applicable law or agreed to in writing, software
13
  distributed under the License is distributed on an "AS IS" BASIS,
14
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
  See the License for the specific language governing permissions and
16
  limitations under the License.
17
-->
18
<!-- $Id$ -->
19
<testcase>
20
  <info>
21
    <p>
22
      This test checks a combination of widows/orphans with a keep-with-next
23
      specified on a first child that generates less lines than the value for
24
      orphans.
25
    </p>
26
  </info>
27
  <fo>
28
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" widows="2" orphans="2" font-size="12pt">
29
      <fo:layout-master-set>
30
        <fo:simple-page-master master-name="simple" page-height="6 * 14.4pt" page-width="210mm">
31
            <fo:region-body />
32
        </fo:simple-page-master>
33
      </fo:layout-master-set>
34
      <fo:page-sequence master-reference="simple">
35
        <fo:flow flow-name="xsl-region-body">
36
          <fo:block id="block-1">
37
            <fo:block keep-with-next="always">
38
                Title
39
            </fo:block>
40
            <fo:block>
41
              <fo:block>line 1</fo:block>
42
              <fo:block>line 2</fo:block>
43
              <fo:block>line 3</fo:block>
44
              <fo:block>line 4</fo:block>
45
            </fo:block>
46
          </fo:block>
47
          <fo:block id="block-2">
48
            <fo:block>
49
              <fo:block keep-with-next="always">
50
                 Title
51
              </fo:block>
52
              <fo:block>
53
                <fo:block>line 1</fo:block>
54
                <fo:block>line 2</fo:block>
55
              </fo:block>
56
            </fo:block>
57
          </fo:block>
58
        </fo:flow>
59
      </fo:page-sequence>
60
    </fo:root>`
61
  </fo>
62
  <checks>
63
    <eval expected="5" xpath="count((//page)[1]//lineArea)" />
64
    <eval expected="3" xpath="count((//page)[2]//lineArea)" />
65
  </checks>
66
</testcase>
(-)test/layoutengine/standard-testcases/block_widows.xml (+143 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
  Licensed to the Apache Software Foundation (ASF) under one or more
4
  contributor license agreements.  See the NOTICE file distributed with
5
  this work for additional information regarding copyright ownership.
6
  The ASF licenses this file to You under the Apache License, Version 2.0
7
  (the "License"); you may not use this file except in compliance with
8
  the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
  Unless required by applicable law or agreed to in writing, software
13
  distributed under the License is distributed on an "AS IS" BASIS,
14
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
  See the License for the specific language governing permissions and
16
  limitations under the License.
17
-->
18
<!-- $Id$ -->
19
<testcase>
20
  <info>
21
    <p>
22
      This test checks the default behavior of the "widows" property.
23
    </p>
24
  </info>
25
  <fo>
26
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
27
      <fo:layout-master-set>
28
        <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in">
29
          <fo:region-body />
30
        </fo:simple-page-master>
31
      </fo:layout-master-set>
32
      <fo:page-sequence master-reference="normal">
33
        <fo:flow flow-name="xsl-region-body">
34
          <fo:block id="block-1">
35
            <!-- Basic test: simple paragraph generating 11 lines.
36
                 2 last lines should be kept together due to initial 
37
                 value for widows
38
              -->
39
            Lorem ipsum dolor sit amet, consectetur
40
            adipiscing elit. Cras placerat, lectus vel
41
            iaculis euismod, ipsum enim dapibus
42
            urna, eu pellentesque velit dolor ac 
43
            purus. Maecenas vitae pulvinar turpis.
44
            Duis venenatis tincidunt velit, fringilla
45
            dignissim sapien faucibus vel. Quisque
46
            placerat ornare consectetur. Aenean
47
            dui tortor, tempor ut convallis in,
48
            fermentum tempor nunc. Class aptent 
49
            taciti sociosqu ad litora torquent per
50
          </fo:block>
51
          <fo:block id="block-2" break-before="page">
52
            <!-- Basic test: simple paragraph generating 11 lines, followed by
53
                 another block.
54
                 A break between lines 10 and 11 is allowed.
55
              -->
56
            Lorem ipsum dolor sit amet, consectetur
57
            adipiscing elit. Cras placerat, lectus vel
58
            iaculis euismod, ipsum enim dapibus
59
            urna, eu pellentesque velit dolor ac 
60
            purus. Maecenas vitae pulvinar turpis.
61
            Duis venenatis tincidunt velit, fringilla
62
            dignissim sapien faucibus vel. Quisque
63
            placerat ornare consectetur. Aenean
64
            dui tortor, tempor ut convallis in,
65
            fermentum tempor nunc. Class aptent 
66
            taciti sociosqu ad litora torquent per
67
            <fo:block>
68
            Lorem ipsum dolor sit amet, consectetur
69
            adipiscing elit. Cras placerat, lectus vel
70
            iaculis euismod, ipsum enim dapibus
71
            urna, eu pellentesque velit dolor ac
72
            </fo:block>
73
          </fo:block>
74
          <fo:block id="block-3" break-before="page">
75
            <!-- Basic test: 1 paragraph consisting of 11 single-line subparagraphs.
76
                 Last 2 lines of the main paragraph should be kept together due to 
77
                 initial value for widows.
78
              -->
79
            <fo:block>
80
              <fo:block>Lorem ipsum</fo:block>
81
              <fo:block>Lorem ipsum</fo:block>
82
              <fo:block>Lorem ipsum</fo:block>
83
              <fo:block>Lorem ipsum</fo:block>
84
              <fo:block>Lorem ipsum</fo:block>
85
              <fo:block>Lorem ipsum</fo:block>
86
              <fo:block>Lorem ipsum</fo:block>
87
              <fo:block>Lorem ipsum</fo:block>
88
              <fo:block>Lorem ipsum</fo:block>
89
              <fo:block>Lorem ipsum</fo:block>
90
              <fo:block>Lorem ipsum</fo:block>
91
            </fo:block>
92
          </fo:block>
93
          <fo:block id="block-4" break-before="page">
94
            <!-- Special case: linefeed-treatment="preserve" (see Bugzilla 44328) -->
95
            <fo:block linefeed-treatment="preserve">Lorem ipsum
96
            dolor sit amet,
97
            consectetur
98
            adipiscing elit.
99
            Cras placerat,
100
            lectus vel
101
            iaculis euismod,
102
            ipsum enim
103
            dapibus urna,
104
            eu pellentesque
105
            velit dolor</fo:block>
106
          </fo:block>
107
          <fo:block id="block-5" break-before="page">
108
            <!-- Special case: 1 paragraph with 10 lines, and 1 with 1.
109
                 Last 2 lines of the first paragraph should be kept
110
                 together with the only line of the second due to initial
111
                 value of widows on the outer block.
112
              -->
113
            <fo:block>
114
            Lorem ipsum dolor sit amet, consectetur
115
            adipiscing elit. Cras placerat, lectus vel
116
            iaculis euismod, ipsum enim dapibus
117
            urna, eu pellentesque velit dolor ac 
118
            purus. Maecenas vitae pulvinar turpis.
119
            Duis venenatis tincidunt velit, fringilla
120
            dignissim sapien faucibus vel. Quisque
121
            placerat ornare consectetur. Aenean
122
            dui tortor, tempor ut convallis in,
123
            fermentum tempor nunc. Class aptent 
124
            </fo:block>
125
            <fo:block>Lorem ipsum</fo:block>
126
          </fo:block>
127
        </fo:flow>
128
      </fo:page-sequence>
129
    </fo:root>
130
  </fo>
131
  <checks>
132
    <eval expected="9" xpath="count((//page)[1]//lineArea)" />
133
    <eval expected="2" xpath="count((//page)[2]//lineArea)" />
134
    <eval expected="10" xpath="count((//page)[3]//lineArea)" />
135
    <eval expected="5" xpath="count((//page)[4]//lineArea)" />
136
    <eval expected="9" xpath="count((//page)[5]//lineArea)" />
137
    <eval expected="2" xpath="count((//page)[6]//lineArea)" />
138
    <eval expected="9" xpath="count((//page)[7]//lineArea)" />
139
    <eval expected="2" xpath="count((//page)[8]//lineArea)" />
140
    <eval expected="8" xpath="count((//page)[9]//lineArea)" />
141
    <eval expected="3" xpath="count((//page)[10]//lineArea)" />
142
  </checks>
143
</testcase>
(-)test/layoutengine/standard-testcases/block_orphans.xml (+167 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
  Licensed to the Apache Software Foundation (ASF) under one or more
4
  contributor license agreements.  See the NOTICE file distributed with
5
  this work for additional information regarding copyright ownership.
6
  The ASF licenses this file to You under the Apache License, Version 2.0
7
  (the "License"); you may not use this file except in compliance with
8
  the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
  Unless required by applicable law or agreed to in writing, software
13
  distributed under the License is distributed on an "AS IS" BASIS,
14
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
  See the License for the specific language governing permissions and
16
  limitations under the License.
17
-->
18
<!-- $Id$ -->
19
<testcase>
20
  <info>
21
    <p>
22
      This test checks the default behavior of the "orphans" property.
23
    </p>
24
  </info>
25
  <fo>
26
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
27
      <fo:layout-master-set>
28
        <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in">
29
          <fo:region-body />
30
        </fo:simple-page-master>
31
      </fo:layout-master-set>
32
      <fo:page-sequence master-reference="normal">
33
        <fo:flow flow-name="xsl-region-body">
34
          <fo:block id="block-1" break-before="page">
35
            <!-- Basic test: 1 paragraph with 9 lines and 1 with 4.
36
                 All 4 lines of the second paragraph should be kept 
37
                 together due to initial value for orphans.
38
              -->
39
            <fo:block>
40
            Lorem ipsum dolor sit amet, consectetur
41
            adipiscing elit. Cras placerat, lectus vel
42
            iaculis euismod, ipsum enim dapibus
43
            urna, eu pellentesque velit dolor ac 
44
            purus. Maecenas vitae pulvinar turpis.
45
            Duis venenatis tincidunt velit, fringilla
46
            dignissim sapien faucibus vel. Quisque
47
            placerat ornare consectetur. Aenean
48
            dui tortor, tempor ut convallis in,
49
            </fo:block>
50
            <fo:block>
51
            Lorem ipsum dolor sit amet, consectetur
52
            adipiscing elit. Cras placerat, lectus vel
53
            iaculis euismod, ipsum enim dapibus
54
            urna, eu pellentesque velit dolor ac
55
            </fo:block>
56
          </fo:block>
57
          <fo:block id="block-2" break-before="page">
58
            <!-- Basic test: 1 block with 9 lines and 1 paragraph with 4 lines.
59
                 A break after the first line of the second paragraph is allowed.
60
              -->
61
            <fo:block>
62
            Lorem ipsum dolor sit amet, consectetur
63
            adipiscing elit. Cras placerat, lectus vel
64
            iaculis euismod, ipsum enim dapibus
65
            urna, eu pellentesque velit dolor ac 
66
            purus. Maecenas vitae pulvinar turpis.
67
            Duis venenatis tincidunt velit, fringilla
68
            dignissim sapien faucibus vel. Quisque
69
            placerat ornare consectetur. Aenean
70
            dui tortor, tempor ut convallis in,
71
            </fo:block>
72
            Lorem ipsum dolor sit amet, consectetur
73
            adipiscing elit. Cras placerat, lectus vel
74
            iaculis euismod, ipsum enim dapibus
75
            urna, eu pellentesque velit dolor ac
76
          </fo:block>
77
          <fo:block id="block-3" break-before="page">
78
            <!-- Basic test: 1 regular paragraph of 9 lines followed by 1 consisting 
79
                 of 4 single-line subparagraphs.
80
                 All 4 lines of the second paragraph should be kept together due
81
                 to initial value for orphans.
82
              -->
83
            <fo:block id="block-3a">
84
            Lorem ipsum dolor sit amet, consectetur
85
            adipiscing elit. Cras placerat, lectus vel
86
            iaculis euismod, ipsum enim dapibus
87
            urna, eu pellentesque velit dolor ac 
88
            purus. Maecenas vitae pulvinar turpis.
89
            Duis venenatis tincidunt velit, fringilla
90
            dignissim sapien faucibus vel. Quisque
91
            placerat ornare consectetur. Aenean
92
            dui tortor, tempor ut convallis in,
93
            </fo:block>
94
            <fo:block id="block-3b">
95
              <fo:block>Lorem ipsum</fo:block>
96
              <fo:block>Lorem ipsum</fo:block>
97
              <fo:block>Lorem ipsum</fo:block>
98
              <fo:block>Lorem ipsum</fo:block>
99
            </fo:block>
100
          </fo:block>
101
          <fo:block id="block-4" break-before="page">
102
            <!-- Special case: linefeed-treatment="preserve" (see Bugzilla 44328) -->
103
            <fo:block>
104
            Lorem ipsum dolor sit amet, consectetur
105
            adipiscing elit. Cras placerat, lectus vel
106
            iaculis euismod, ipsum enim dapibus
107
            urna, eu pellentesque velit dolor ac 
108
            purus. Maecenas vitae pulvinar turpis.
109
            Duis venenatis tincidunt velit, fringilla
110
            dignissim sapien faucibus vel. Quisque
111
            placerat ornare consectetur. Aenean
112
            dui tortor, tempor ut convallis in,
113
            </fo:block>
114
            <fo:block linefeed-treatment="preserve">Lorem ipsum
115
            dolor sit amet,
116
            consectetur
117
            velit dolor</fo:block>
118
          </fo:block>
119
          <fo:block id="block-5" break-before="page" widows="1">
120
            <!-- Last but not least, demonstrate peculiar side-effect in case
121
                 of convoluted nesting...
122
                 Even though widows would allow a break before the last line,
123
                 all 10 last lines are moved to the next page due to stacked 
124
                 orphans constraints
125
              -->
126
            <fo:block id="level-1">Lorem ipsum
127
              <fo:block>Lorem ipsum</fo:block>
128
              <fo:block id="level-2">Lorem ipsum
129
                <fo:block id="level-3">Lorem ipsum
130
                  <fo:block id="level-4">Lorem ipsum
131
                    <fo:block id="level-5">Lorem ipsum
132
                      <fo:block id="level-6">Lorem ipsum
133
                        <fo:block id="level-7">Lorem ipsum
134
                          <fo:block id="level-8">Lorem ipsum
135
                            <fo:block id="level-9">Lorem ipsum
136
                              <fo:block id="level-10">Lorem ipsum
137
                                <fo:block id="level-11">
138
                                Lorem ipsum
139
                                </fo:block>
140
                              </fo:block>
141
                            </fo:block>
142
                          </fo:block>
143
                        </fo:block>
144
                      </fo:block>
145
                    </fo:block>
146
                  </fo:block>
147
                </fo:block>
148
              </fo:block>
149
            </fo:block>
150
          </fo:block>
151
        </fo:flow>
152
      </fo:page-sequence>
153
    </fo:root>
154
  </fo>
155
  <checks>
156
    <eval expected="9" xpath="count((//page)[1]//lineArea)" />
157
    <eval expected="4" xpath="count((//page)[2]//lineArea)" />
158
    <eval expected="10" xpath="count((//page)[3]//lineArea)" />
159
    <eval expected="3" xpath="count((//page)[4]//lineArea)" />
160
    <eval expected="9" xpath="count((//page)[5]//lineArea)" />
161
    <eval expected="4" xpath="count((//page)[6]//lineArea)" />
162
    <eval expected="9" xpath="count((//page)[7]//lineArea)" />
163
    <eval expected="4" xpath="count((//page)[8]//lineArea)" />
164
    <eval expected="2" xpath="count((//page)[9]//lineArea)" />
165
    <eval expected="10" xpath="count((//page)[10]//lineArea)" />
166
  </checks>
167
</testcase>
(-)test/layoutengine/standard-testcases/block_list-block_orphans_widows.xml (+128 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
  Licensed to the Apache Software Foundation (ASF) under one or more
4
  contributor license agreements.  See the NOTICE file distributed with
5
  this work for additional information regarding copyright ownership.
6
  The ASF licenses this file to You under the Apache License, Version 2.0
7
  (the "License"); you may not use this file except in compliance with
8
  the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
  Unless required by applicable law or agreed to in writing, software
13
  distributed under the License is distributed on an "AS IS" BASIS,
14
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
  See the License for the specific language governing permissions and
16
  limitations under the License.
17
-->
18
<!-- $Id$ -->
19
<testcase>
20
  <info>
21
    <p>
22
      This test checks the behavior of the "orphans" and "widows" properties
23
      in case list-blocks are nested in blocks.
24
    </p>
25
  </info>
26
  <fo>
27
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
28
      <fo:layout-master-set>
29
        <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in">
30
          <fo:region-body />
31
        </fo:simple-page-master>
32
      </fo:layout-master-set>
33
      <fo:page-sequence master-reference="normal">
34
        <fo:flow flow-name="xsl-region-body">
35
          <fo:block id="block-1">
36
            <!-- Check that the last list-item is not unnecessarily kept together.
37
                 The inner block's widows constraint causes the list-layout code
38
                 to generate a merged last box, which as a single box, satisfies 
39
                 the containing block's constraint.
40
              -->
41
            <fo:list-block>
42
              <fo:list-item>
43
                <fo:list-item-label><fo:block /></fo:list-item-label>
44
                <fo:list-item-body>
45
                  <fo:block>
46
                  Lorem ipsum dolor sit amet, consectetur
47
                  adipiscing elit. Cras placerat, lectus vel
48
                  iaculis euismod, ipsum enim dapibus
49
                  urna, eu pellentesque velit dolor ac 
50
                  </fo:block>
51
                </fo:list-item-body>
52
              </fo:list-item>
53
              <fo:list-item>
54
                <fo:list-item-label><fo:block /></fo:list-item-label>
55
                <fo:list-item-body>
56
                  <fo:block>
57
                  purus. Maecenas vitae pulvinar turpis.
58
                  Duis venenatis tincidunt velit, fringilla
59
                  dignissim sapien faucibus vel. Quisque
60
                  placerat ornare consectetur. Aenean
61
                  </fo:block>
62
                </fo:list-item-body>
63
              </fo:list-item>
64
              <fo:list-item>
65
                <fo:list-item-label><fo:block /></fo:list-item-label>
66
                <fo:list-item-body>
67
                  <fo:block>
68
                  Lorem ipsum dolor sit amet, consectetur
69
                  adipiscing elit. Cras placerat, lectus vel
70
                  iaculis euismod, ipsum enim dapibus
71
                  urna, eu pellentesque velit dolor ac 
72
                  </fo:block>
73
                </fo:list-item-body>
74
              </fo:list-item>
75
            </fo:list-block>
76
          </fo:block>
77
          <fo:block id="block-2" break-before="page">
78
            <!-- Check that the first list-item is not unnecessarily kept together.
79
                 The inner block's widows constraint causes the list-layout code
80
                 to generate a merged first box, which as a single box, satisfies 
81
                 the containing block's constraint.
82
              -->
83
            Lorem ipsum dolor sit amet, consectetur
84
            adipiscing elit. Cras placerat, lectus vel
85
            iaculis euismod, ipsum enim dapibus
86
            urna, eu pellentesque velit dolor ac 
87
            purus. Maecenas vitae pulvinar turpis.
88
            Duis venenatis tincidunt velit, fringilla
89
            dignissim sapien faucibus vel. Quisque
90
            placerat ornare consectetur. Aenean
91
            <fo:block id="block-2a">
92
              <fo:list-block>
93
                <fo:list-item>
94
                <fo:list-item-label><fo:block /></fo:list-item-label>
95
                  <fo:list-item-body>
96
                    <fo:block>
97
                    Lorem ipsum dolor sit amet, consectetur
98
                    adipiscing elit. Cras placerat, lectus vel
99
                    iaculis euismod, ipsum enim dapibus
100
                    urna, eu pellentesque velit dolor ac 
101
                    </fo:block>
102
                  </fo:list-item-body>
103
                </fo:list-item>
104
                <fo:list-item>
105
                <fo:list-item-label><fo:block /></fo:list-item-label>
106
                  <fo:list-item-body>
107
                    <fo:block>
108
                    purus. Maecenas vitae pulvinar turpis.
109
                    Duis venenatis tincidunt velit, fringilla
110
                    dignissim sapien faucibus vel. Quisque
111
                    placerat ornare consectetur. Aenean
112
                    </fo:block>
113
                  </fo:list-item-body>
114
                </fo:list-item>
115
              </fo:list-block>
116
            </fo:block>
117
          </fo:block>
118
        </fo:flow>
119
      </fo:page-sequence>
120
    </fo:root>
121
  </fo>
122
  <checks>
123
    <eval expected="10" xpath="count((//page)[1]//lineArea)" />
124
    <eval expected="2" xpath="count((//page)[2]//lineArea)" />
125
    <eval expected="10" xpath="count((//page)[3]//lineArea)" />
126
    <eval expected="6" xpath="count((//page)[4]//lineArea)" />
127
  </checks>
128
</testcase>
(-)src/java/org/apache/fop/layoutmgr/table/TableStepper.java (-5 / +7 lines)
Lines 181-186 Link Here
181
        TableContentPosition lastTCPos = null;
181
        TableContentPosition lastTCPos = null;
182
        LinkedList returnList = new LinkedList();
182
        LinkedList returnList = new LinkedList();
183
        int laststep = 0;
183
        int laststep = 0;
184
        int stepLines;
184
        int step = getFirstStep();
185
        int step = getFirstStep();
185
        do {
186
        do {
186
            int maxRemainingHeight = getMaxRemainingHeight();
187
            int maxRemainingHeight = getMaxRemainingHeight();
Lines 201-210 Link Here
201
            LinkedList footnoteList = new LinkedList();
202
            LinkedList footnoteList = new LinkedList();
202
            //Put all involved grid units into a list
203
            //Put all involved grid units into a list
203
            List cellParts = new java.util.ArrayList(columnCount);
204
            List cellParts = new java.util.ArrayList(columnCount);
205
            stepLines = 0;
204
            for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
206
            for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
205
                ActiveCell activeCell = (ActiveCell) iter.next();
207
                ActiveCell activeCell = (ActiveCell) iter.next();
206
                CellPart part = activeCell.createCellPart();
208
                CellPart part = activeCell.createCellPart();
207
                cellParts.add(part);
209
                cellParts.add(part);
210
                int partLines = part.getLineCount();
211
                if (partLines > stepLines) {
212
                    stepLines = partLines;
213
                }
208
                activeCell.addFootnotes(footnoteList);
214
                activeCell.addFootnotes(footnoteList);
209
            }
215
            }
210
216
Lines 220-230 Link Here
220
            lastTCPos = tcpos;
226
            lastTCPos = tcpos;
221
227
222
            // TODO TableStepper should remain as footnote-agnostic as possible
228
            // TODO TableStepper should remain as footnote-agnostic as possible
223
            if (footnoteList.isEmpty()) {
229
            returnList.add(new KnuthBlockBox(boxLen, tcpos, false, stepLines, footnoteList));
224
                returnList.add(new KnuthBox(boxLen, tcpos, false));
225
            } else {
226
                returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false));
227
            }
228
230
229
            int effPenaltyLen = Math.max(0, penaltyOrGlueLen);
231
            int effPenaltyLen = Math.max(0, penaltyOrGlueLen);
230
            TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM());
232
            TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM());
(-)src/java/org/apache/fop/layoutmgr/table/CellPart.java (+5 lines)
Lines 20-25 Link Here
20
package org.apache.fop.layoutmgr.table;
20
package org.apache.fop.layoutmgr.table;
21
21
22
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
22
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
23
import org.apache.fop.layoutmgr.ElementListUtils;
23
24
24
/**
25
/**
25
 * Represents a non-divisible part of a grid unit. Used by the table stepper.
26
 * Represents a non-divisible part of a grid unit. Used by the table stepper.
Lines 117-122 Link Here
117
        return condAfterContentLength;
118
        return condAfterContentLength;
118
    }
119
    }
119
120
121
    int getLineCount() {
122
        return ElementListUtils.getLineCount(pgu.getElements().subList(start, end + 1));
123
    }
124
120
    /** {@inheritDoc} */
125
    /** {@inheritDoc} */
121
    public String toString() {
126
    public String toString() {
122
        StringBuffer sb = new StringBuffer("Part: ");
127
        StringBuffer sb = new StringBuffer("Part: ");
(-)src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java (-7 / +9 lines)
Lines 316-321 Link Here
316
            // footnote-agnostic as possible
316
            // footnote-agnostic as possible
317
            LinkedList<FootnoteBodyLayoutManager> footnoteList = null;
317
            LinkedList<FootnoteBodyLayoutManager> footnoteList = null;
318
            ListElement el;
318
            ListElement el;
319
            int stepLines = 0;
319
            for (int i = 0; i < elementLists.length; i++) {
320
            for (int i = 0; i < elementLists.length; i++) {
320
                for (int j = start[i]; j <= end[i]; j++) {
321
                for (int j = start[i]; j <= end[i]; j++) {
321
                    el = (ListElement) elementLists[i].get(j);
322
                    el = (ListElement) elementLists[i].get(j);
Lines 326-342 Link Here
326
                        footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs());
327
                        footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs());
327
                    }
328
                    }
328
                }
329
                }
329
            }
330
                int lineCount = ElementListUtils.getLineCount(
331
                        elementLists[i].subList(start[i], end[i] + 1));
332
                if (lineCount > stepLines) {
333
                    stepLines = lineCount;
334
                }
335
            }
330
336
331
            // add the new elements
337
            // add the new elements
332
            addedBoxHeight += boxHeight;
338
            addedBoxHeight += boxHeight;
333
            ListItemPosition stepPosition = new ListItemPosition(this,
339
            ListItemPosition stepPosition = new ListItemPosition(this,
334
                    start[0], end[0], start[1], end[1]);
340
                    start[0], end[0], start[1], end[1]);
335
            if (footnoteList == null) {
341
            returnList.add(
336
                returnList.add(new KnuthBox(boxHeight, stepPosition, false));
342
                    new KnuthBlockBox(boxHeight, stepPosition, false, stepLines, footnoteList));
337
            } else {
338
                returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false));
339
            }
340
343
341
            if (addedBoxHeight < totalHeight) {
344
            if (addedBoxHeight < totalHeight) {
342
                Keep keep = keepWithNextActive.compare(getKeepTogether());
345
                Keep keep = keepWithNextActive.compare(getKeepTogether());
Lines 694-699 Link Here
694
        body.reset();
697
        body.reset();
695
    }
698
    }
696
699
697
698
}
700
}
699
701
(-)src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java (-31 / +111 lines)
Lines 19-24 Link Here
19
19
20
package org.apache.fop.layoutmgr;
20
package org.apache.fop.layoutmgr;
21
21
22
import java.util.Collections;
22
import java.util.LinkedList;
23
import java.util.LinkedList;
23
import java.util.List;
24
import java.util.List;
24
25
Lines 29-109 Link Here
29
 */
30
 */
30
public class KnuthBlockBox extends KnuthBox {
31
public class KnuthBlockBox extends KnuthBox {
31
32
33
    /**
34
     * Helper class to encapsulate information related to
35
     * footnotes that are associated with this box
36
     */
37
    static class FootnoteInfo {
38
39
        private final List<FootnoteBodyLayoutManager> footnoteList;
40
        /** List of Knuth elements. This is a list of LinkedList elements. */
41
        private List<List<ListElement>> elementLists;
42
43
44
        /**
45
         * Creates a new instance initialized with the given list of
46
         * footnote layout managers.
47
         * @param footnoteList  the list of LMs
48
         */
49
        FootnoteInfo(List<FootnoteBodyLayoutManager> footnoteList) {
50
            this.footnoteList = footnoteList;
51
        }
52
53
        /**
54
         * Adds the given list to the list of elements (generated by the LMs in
55
         * {@code footnoteList} as the footnote content).
56
         * @param elementList
57
         */
58
        void addElementList(List<ListElement> elementList) {
59
            if (elementLists == null) {
60
                elementLists = new LinkedList<List<ListElement>>();
61
            }
62
            elementLists.add(elementList);
63
        }
64
    }
65
32
    private MinOptMax ipdRange;
66
    private MinOptMax ipdRange;
33
    /**
67
    /**
34
     * Natural width of the line represented by this box. In addition to ipdRange because
68
     * Natural width of the line represented by this box. In addition to ipdRange because
35
     * it isn't possible to get the opt value stored in a MinOptMax object.
69
     * it isn't possible to get the opt value stored in a MinOptMax object.
36
     */
70
     */
37
    private int bpd;
71
    private int bpd;
38
    private List footnoteList;
39
    /** List of Knuth elements. This is a list of LinkedList elements. */
40
    private List elementLists = null;
41
72
73
    private FootnoteInfo footnoteInfo;
74
75
    private int lineCount;
76
42
    /**
77
    /**
43
     * Creates a new box.
78
     * Creates a new box.
44
     *
79
     *
45
     * @param width     block progression dimension of this box
80
     * @param width     block progression dimension of this box
46
     * @param range     min, opt, max inline progression dimension of this box
81
     * @param pos       the {@link Position} stored in this box
47
     * @param bpdim     natural width of the line represented by this box.
48
     * @param pos       the Position stored in this box
49
     * @param auxiliary is this box auxiliary?
82
     * @param auxiliary is this box auxiliary?
50
     */
83
     */
51
    public KnuthBlockBox(int width, MinOptMax range, int bpdim, Position pos, boolean auxiliary) {
84
    public KnuthBlockBox(int width, Position pos, boolean auxiliary) {
52
        super(width, pos, auxiliary);
85
        super(width, pos, auxiliary);
53
        ipdRange = range;
86
        // default auxiliary box does not count as a line
54
        bpd = bpdim;
87
        this.lineCount = (auxiliary ? 0 : 1);
55
        footnoteList = new LinkedList();
56
    }
88
    }
57
89
58
    /**
90
    /**
59
     * Creates a new box.
91
     * Creates a new box spanning the number of lines specified.
60
     *
92
     *
61
     * @param width     block progression dimension of this box
93
     * @param width     block progression dimension of this box
62
     * @param list      footnotes cited by elements in this box. The list contains the corresponding
94
     * @param pos       the {@link Position} stored in this box
63
     *                  FootnoteBodyLayoutManagers
64
     * @param pos       the Position stored in this box
65
     * @param auxiliary is this box auxiliary?
95
     * @param auxiliary is this box auxiliary?
96
     * @param lineCount the number of lines stored in this box
66
     */
97
     */
67
    public KnuthBlockBox(int width, List list, Position pos, boolean auxiliary) {
98
    public KnuthBlockBox(int width, Position pos, boolean auxiliary, int lineCount) {
68
        super(width, pos, auxiliary);
99
        super(width, pos, auxiliary);
69
        ipdRange = MinOptMax.ZERO;
100
        this.lineCount = lineCount;
70
        bpd = 0;
71
        footnoteList = new LinkedList(list);
72
    }
101
    }
73
102
74
    /**
103
    /**
104
     * Creates a new box, with the specified range of IPD and fixed BPD.
105
     * (used for vertical justification of lines)
106
     *
107
     * @param width     block progression dimension of this box
108
     * @param pos       the {@link Position} stored in this box
109
     * @param auxiliary is this box auxiliary?
110
     * @param range     min, opt, max inline progression dimension of this box
111
     * @param bpdim     natural width of the line represented by this box.
112
     */
113
    public KnuthBlockBox(int width, Position pos, boolean auxiliary, MinOptMax range, int bpdim) {
114
        this(width, pos, auxiliary);
115
        this.ipdRange = range;
116
        this.bpd = bpdim;
117
    }
118
119
    /**
120
     * Creates a new box spanning the specified number of lines, and associates
121
     * it with the given list of footnotes.
122
     *
123
     * @param width     block progression dimension of this box
124
     * @param pos       the {@link Position} stored in this box
125
     * @param auxiliary is this box auxiliary?
126
     * @param footnoteList      footnotes cited by elements in this box.
127
     *                  The list contains the corresponding FootnoteBodyLayoutManagers
128
     * @param lineCount the number of lines stored in this box
129
     */
130
    public KnuthBlockBox(int width, Position pos, boolean auxiliary,
131
                         int lineCount, List footnoteList) {
132
        this(width, pos, auxiliary, lineCount);
133
        this.ipdRange = MinOptMax.ZERO;
134
        this.bpd = 0;
135
        if (footnoteList != null && !footnoteList.isEmpty()) {
136
            this.footnoteInfo = new FootnoteInfo(footnoteList);
137
        }
138
    }
139
140
    /**
75
     * @return the LMs for the footnotes cited in this box.
141
     * @return the LMs for the footnotes cited in this box.
76
     */
142
     */
77
    public List getFootnoteBodyLMs() {
143
    public List<FootnoteBodyLayoutManager> getFootnoteBodyLMs() {
78
        return footnoteList;
144
        return (footnoteInfo == null
145
                ? Collections.<FootnoteBodyLayoutManager>emptyList()
146
                : footnoteInfo.footnoteList);
79
    }
147
    }
80
148
81
    /**
149
    /**
82
     * @return true if this box contains footnote citations.
150
     * Returns {@code true} if this box has anchors for footnotes.
151
     * @return  {@code true} if this box has anchors for footnotes, {@code false} otherwise
83
     */
152
     */
84
    public boolean hasAnchors() {
153
    public boolean hasAnchors() {
85
        return (footnoteList.size() > 0);
154
        return (footnoteInfo != null
155
                && footnoteInfo.footnoteList != null
156
                && !footnoteInfo.footnoteList.isEmpty());
86
    }
157
    }
87
158
88
    /**
159
    /**
89
     * Adds the given list of Knuth elements to this box' list of elements.
160
     * Adds the given list of Knuth elements to this box' list of elements.
161
     * <p>Note: if the box is not associated with footnotes, the parameter is ignored.
90
     *
162
     *
91
     * @param list elements corresponding to a footnote body
163
     * @param list elements corresponding to a footnote body
92
     */
164
     */
93
    public void addElementList(List list) {
165
    void addElementList(List list) {
94
        if (elementLists == null) {
166
        assert (hasAnchors());
95
            elementLists = new LinkedList();
167
        footnoteInfo.addElementList(list);
96
        }
168
    }
97
        elementLists.add(list);
98
    }
99
169
100
    /**
170
    /**
101
     * Returns the list of Knuth sequences registered by this box.
171
     * Returns the list of Knuth sequences registered by this box.
102
     *
172
     *
103
     * @return a list of KnuthElement sequences corresponding to footnotes cited in this box
173
     * @return a list of KnuthElement sequences corresponding to footnotes cited in this box
104
     */
174
     */
105
    public List getElementLists() {
175
    List getElementLists() {
106
        return elementLists;
176
        return footnoteInfo == null
177
            ? Collections.<List<ListElement>>emptyList()
178
            : footnoteInfo.elementLists;
107
    }
179
    }
108
180
109
    /**
181
    /**
Lines 122-125 Link Here
122
    public int getBPD() {
194
    public int getBPD() {
123
        return bpd;
195
        return bpd;
124
    }
196
    }
125
}
197
198
    /**
199
     * Returns the (maximum) number of lines of content that this box represents
200
     * @return  the number of lines in this box
201
     */
202
    public int getLineCount() {
203
        return lineCount;
204
    }
205
}
(-)src/java/org/apache/fop/layoutmgr/KnuthBox.java (-3 / +2 lines)
Lines 45-56 Link Here
45
        super(width, pos, auxiliary);
45
        super(width, pos, auxiliary);
46
    }
46
    }
47
47
48
    /** {@inheritDoc} */
48
    @Override
49
    public boolean isBox() {
49
    public boolean isBox() {
50
        return true;
50
        return true;
51
    }
51
    }
52
52
53
    /** {@inheritDoc} */
53
    @Override
54
    public String toString() {
54
    public String toString() {
55
        StringBuffer buffer = new StringBuffer(64);
55
        StringBuffer buffer = new StringBuffer(64);
56
        if (isAuxiliary()) {
56
        if (isAuxiliary()) {
Lines 61-65 Link Here
61
        buffer.append(getWidth());
61
        buffer.append(getWidth());
62
        return buffer.toString();
62
        return buffer.toString();
63
    }
63
    }
64
65
}
64
}
(-)src/java/org/apache/fop/layoutmgr/KnuthPenalty.java (+3 lines)
Lines 46-51 Link Here
46
    /** Dummy, zero-width penalty */
46
    /** Dummy, zero-width penalty */
47
    public static final KnuthPenalty DUMMY_ZERO_PENALTY
47
    public static final KnuthPenalty DUMMY_ZERO_PENALTY
48
            = new KnuthPenalty(0, 0, false, null, true);
48
            = new KnuthPenalty(0, 0, false, null, true);
49
    /** Dummy break inhibitor */
50
    public static final KnuthPenalty DUMMY_INFINITE_PENALTY
51
            = new KnuthPenalty(0, KnuthElement.INFINITE, false, null, true);
49
52
50
    private int penalty;
53
    private int penalty;
51
    private boolean penaltyFlagged;
54
    private boolean penaltyFlagged;
(-)src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java (-8 / +102 lines)
Lines 66-71 Link Here
66
    private MinOptMax effSpaceBefore;
66
    private MinOptMax effSpaceBefore;
67
    private MinOptMax effSpaceAfter;
67
    private MinOptMax effSpaceAfter;
68
68
69
    private int orphans = 2;
70
    private int widows = 2;
71
69
    /**
72
    /**
70
     * Creates a new BlockLayoutManager.
73
     * Creates a new BlockLayoutManager.
71
     * @param inBlock the block FO object to create the layout manager for.
74
     * @param inBlock the block FO object to create the layout manager for.
Lines 97-102 Link Here
97
                                    .getOptimum(this).getLength().getValue(this);
100
                                    .getOptimum(this).getLength().getValue(this);
98
        adjustedSpaceAfter = fo.getCommonMarginBlock().spaceAfter.getSpace()
101
        adjustedSpaceAfter = fo.getCommonMarginBlock().spaceAfter.getSpace()
99
                                    .getOptimum(this).getLength().getValue(this);
102
                                    .getOptimum(this).getLength().getValue(this);
103
        orphans = fo.getOrphans();
104
        widows = fo.getWidows();
100
    }
105
    }
101
106
102
    /** {@inheritDoc} */
107
    /** {@inheritDoc} */
Lines 110-119 Link Here
110
    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
115
    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
111
            Position restartPosition, LayoutManager restartAtLM) {
116
            Position restartPosition, LayoutManager restartAtLM) {
112
        resetSpaces();
117
        resetSpaces();
113
        return super.getNextKnuthElements(
118
119
        List<ListElement> contentList = super.getNextKnuthElements(
114
                context, alignment, lmStack, restartPosition, restartAtLM);
120
                context, alignment, lmStack, restartPosition, restartAtLM);
115
    }
121
122
        if (!this.hasNextChildLM()) {
123
            // handle widows
124
            int lineCount = 0, boxCount = 0, index = contentList.size();
125
            ListElement current;
126
            for (ListIterator<ListElement> it = contentList.listIterator(contentList.size());
127
                    it.hasPrevious();) {
128
                current = it.previous();
129
                index--;
130
                if (current.isBox() && !((KnuthBox) current).isAuxiliary()) {
131
                    boxCount++;
132
                    // non-auxiliary box => increase lineCount
133
                    if (current instanceof KnuthBlockBox) {
134
                        lineCount += ((KnuthBlockBox) current).getLineCount();
135
                    } else {
136
                        // assume one line
137
                        lineCount++;
138
                    }
139
                    if (lineCount >= widows) {
140
                        break;
141
                    }
142
                }
143
            }
144
            // if the sublist only consists of boxes, nothing to remove
145
            if (index <= (contentList.size() - boxCount)) {
146
                ElementListUtils.removeLegalBreaks(
147
                        contentList.subList(index, contentList.size()));
148
            }
149
        }
116
150
151
        return contentList;
152
    }
153
117
    /**
154
    /**
118
     * Overridden to take into account that the childLM may be the block's
155
     * Overridden to take into account that the childLM may be the block's
119
     * {@link LineLayoutManager}.
156
     * {@link LineLayoutManager}.
Lines 132-156 Link Here
132
            // nop; will have been properly set by makeChildLayoutContext()
169
            // nop; will have been properly set by makeChildLayoutContext()
133
        }
170
        }
134
171
135
        if (childLM == this.childLMs.get(0)) {
172
        boolean isFirst = childLM == this.childLMs.get(0);
173
        if (isFirst) {
136
            childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
174
            childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
137
            //Handled already by the parent (break collapsing, see above)
175
            //Handled already by the parent (break collapsing, see above)
138
        }
176
        }
139
177
178
        List<ListElement> childElements;
140
        if (lmStack == null) {
179
        if (lmStack == null) {
141
            return childLM.getNextKnuthElements(childLC, alignment);
180
            childElements = childLM.getNextKnuthElements(childLC, alignment);
142
        } else {
181
        } else {
143
            if (childLM instanceof LineLayoutManager) {
182
            if (childLM instanceof LineLayoutManager) {
144
                assert (restartPosition instanceof LeafPosition);
183
                assert (restartPosition instanceof LeafPosition);
145
                return ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment,
184
                childElements
185
                        = ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment,
146
                        (LeafPosition) restartPosition);
186
                            (LeafPosition) restartPosition);
147
            } else {
187
            } else {
148
                return childLM.getNextKnuthElements(childLC, alignment,
188
                childElements = childLM.getNextKnuthElements(childLC, alignment,
149
                        lmStack, restartPosition, restartAtLM);
189
                        lmStack, restartPosition, restartAtLM);
150
            }
190
            }
151
        }
191
        }
152
    }
192
193
        if (childElements != null && isFirst) {
194
            // handle orphans
195
            int lineCount = 0, boxCount = 0, endIndex = 0;
196
            boolean orphansSatisfied = false;
197
            ListElement current;
198
            for (ListIterator<ListElement> it = childElements.listIterator(); it.hasNext();) {
199
                current = it.next();
200
                endIndex++;
201
                if (current.isBox() && !((KnuthBox) current).isAuxiliary()) {
202
                    boxCount++;
203
                    // non-auxiliary box => increase lineCount
204
                    if (current instanceof KnuthBlockBox) {
205
                        lineCount += ((KnuthBlockBox) current).getLineCount();
206
                    } else {
207
                        // assume one line
208
                        lineCount++;
209
                    }
210
                    if (lineCount >= orphans) {
211
                        break;
212
                    }
213
                }
214
            }
215
            // if the sublist only consists of boxes, nothing to remove
216
            if (endIndex > boxCount) {
217
                ElementListUtils.removeLegalBreaks(childElements.subList(0, endIndex));
218
            }
219
        }
153
220
221
        return childElements;
222
    }
223
224
    /**
225
     * Overridden to deal with a special case for the "orphans" property.
226
     * {@inheritDoc}
227
     */
228
    @Override
229
    protected void addInBetweenBreak(List<ListElement> contentList,
230
                                     LayoutContext parentLC, LayoutContext childLC) {
231
232
        if (this.childLMs.size() > 1
233
                && this.curChildLM == this.childLMs.get(1)) {
234
            // Special case - second childLM:
235
            // If the content so far did not produce enough lines to satisfy
236
            // this LM's orphans constraint, avoid adding a break possibility.
237
            if (ElementListUtils.getLineCount(contentList) < orphans) {
238
                // Make sure pending keeps are cleared (= satisfied by the orphans constraint)
239
                parentLC.clearKeepWithNextPending();
240
                childLC.clearKeepWithPreviousPending();
241
                return;
242
            }
243
        }
244
245
        super.addInBetweenBreak(contentList, parentLC, childLC);
246
    }
247
154
    private void resetSpaces() {
248
    private void resetSpaces() {
155
        this.discardBorderBefore = false;
249
        this.discardBorderBefore = false;
156
        this.discardBorderAfter = false;
250
        this.discardBorderAfter = false;
(-)src/java/org/apache/fop/layoutmgr/ElementListUtils.java (+81 lines)
Lines 133-138 Link Here
133
    }
133
    }
134
134
135
    /**
135
    /**
136
     * Removes all legal break points from the given {@code List<ListElement>}.
137
     * That is, this method:<br/>
138
     * <ul>
139
     *   <li>removes penalties in between two boxes</li>
140
     *   <li>converts other penalties to inhibit breaks</li>
141
     *   <li>converts glues following a box into auxiliary boxes
142
     *       or penalty-glue sequences</li>
143
     * </ul>
144
     * <br/>
145
     * <em>Note: leading glues will not be treated, as it is assumed nothing precedes
146
     * the first element of the given list. Similarly, trailing penalties would just be set
147
     * to {@link KnuthElement#INFINITE}, as there is never a following box.<br/>
148
     * Care should be taken to provide as much context elements as required. Ideally, the
149
     * list should start with a box and end with a box or glue.</em>
150
     *
151
     * @param elements  the element list from which the breaks will be removed
152
     */
153
    public static void removeLegalBreaks(List<ListElement> elements) {
154
155
        ListElement current;
156
        boolean previousIsBox = false;
157
158
        for (ListIterator<ListElement> it = elements.listIterator(); it.hasNext();) {
159
160
            current = it.next();
161
162
            if (current.isBox()) {
163
                previousIsBox = true;
164
                continue;
165
            } else if (current.isGlue() && previousIsBox) {
166
                KnuthGlue glue = (KnuthGlue)current;
167
                if (glue.getStretch() == 0 && glue.getShrink() == 0) {
168
                    // non-stretchable glue => replace with a box of the same width
169
                    it.set(new KnuthBox(glue.getWidth(), glue.getPosition(), true));
170
                } else {
171
                    // stretchable glue => add break-inhibitor
172
                    it.previous();
173
                    it.add(KnuthPenalty.DUMMY_INFINITE_PENALTY);
174
                    it.next();
175
                }
176
            } else if (current.isPenalty() || current instanceof BreakElement
177
                        && !current.isForcedBreak()) {
178
                boolean nextIsBox = (it.hasNext() && it.next().isBox());
179
                it.previous();
180
                if (previousIsBox && nextIsBox) {
181
                    // penalty or BreakElement in between boxes => remove
182
                    it.previous();
183
                    it.remove();
184
                } else {
185
                    if (current.isPenalty()) {
186
                        ((KnuthPenalty)current).setPenalty(KnuthElement.INFINITE);
187
                    } else {
188
                        ((BreakElement)current).setPenaltyValue(KnuthElement.INFINITE);
189
                    }
190
                }
191
            }
192
            previousIsBox = false;
193
        }
194
    }
195
196
    /**
197
     * Obtains the (maximum) number of lines in the given list.
198
     * @param elements  the list to count the lines for
199
     * @return  the number of lines
200
     */
201
    public static int getLineCount(List<ListElement> elements) {
202
        int lineCount = 0;
203
        for (ListElement current : elements) {
204
            if (current.isBox() && !((KnuthBox) current).isAuxiliary()) {
205
                if (current instanceof KnuthBlockBox) {
206
                    lineCount += ((KnuthBlockBox) current).getLineCount();
207
                } else {
208
                    // assume one line
209
                    lineCount++;
210
                }
211
            }
212
        }
213
        return lineCount;
214
    }
215
216
    /**
136
     * Calculates the content length of the given element list. Warning: It doesn't take any
217
     * Calculates the content length of the given element list. Warning: It doesn't take any
137
     * stretch and shrink possibilities into account.
218
     * stretch and shrink possibilities into account.
138
     * @param elems the element list
219
     * @param elems the element list
(-)src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (-22 / +22 lines)
Lines 656-661 Link Here
656
                /* curLM.getNextKnuthElements() returned null or an empty list;
656
                /* curLM.getNextKnuthElements() returned null or an empty list;
657
                 * this can happen if there is nothing more to layout,
657
                 * this can happen if there is nothing more to layout,
658
                 * so just iterate once more to see if there are other children */
658
                 * so just iterate once more to see if there are other children */
659
                curLM = (InlineLevelLayoutManager) getChildLM();
659
                continue;
660
                continue;
660
            }
661
            }
661
662
Lines 919-928 Link Here
919
                for (int i = 0;
920
                for (int i = 0;
920
                        i < llPoss.getChosenLineCount();
921
                        i < llPoss.getChosenLineCount();
921
                        i++) {
922
                        i++) {
922
                    if (returnList.size() > 0
923
                    if (returnList.size() > 0 && i > 0) {
923
                            && i > 0 //if i==0 break generated above already
924
                            && i >= fobj.getOrphans()
925
                            && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
926
                        // penalty allowing a page break between lines
924
                        // penalty allowing a page break between lines
927
                        Keep keep = getKeepTogether();
925
                        Keep keep = getKeepTogether();
928
                        returnList.add(new BreakElement(
926
                        returnList.add(new BreakElement(
Lines 932-955 Link Here
932
                                    context));
930
                                    context));
933
                    }
931
                    }
934
                    endIndex = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos();
932
                    endIndex = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos();
933
935
                    // create a list of the FootnoteBodyLM handling footnotes
934
                    // create a list of the FootnoteBodyLM handling footnotes
936
                    // whose citations are in this line
935
                    // whose citations are in this line
937
                    List<LayoutManager> footnoteList = new LinkedList<LayoutManager>();
936
                    List<LayoutManager> footnoteList = new LinkedList<LayoutManager>();
938
                    ListIterator<KnuthElement> elementIterator = seq.listIterator(startIndex);
937
                    for (Object o : seq.subList(startIndex, endIndex)) {
939
                    while (elementIterator.nextIndex() <= endIndex) {
938
                        //TODO: remove cast once KnuthSequence can be made type-safe
940
                        KnuthElement element = elementIterator.next();
939
                        KnuthElement el = (KnuthElement) o;
941
                        if (element instanceof KnuthInlineBox
940
                        if (el instanceof KnuthInlineBox
942
                                && ((KnuthInlineBox) element).isAnchor()) {
941
                                && ((KnuthInlineBox) el).isAnchor()) {
943
                            footnoteList.add(((KnuthInlineBox) element).getFootnoteBodyLM());
942
                            footnoteList.add(((KnuthInlineBox) el).getFootnoteBodyLM());
944
                        } else if (element instanceof KnuthBlockBox) {
943
                        } else if (el instanceof KnuthBlockBox
945
                            footnoteList.addAll(((KnuthBlockBox) element).getFootnoteBodyLMs());
944
                                && ((KnuthBlockBox) el).hasAnchors()) {
945
                            footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs());
946
                        }
946
                        }
947
                    }
947
                    }
948
                    startIndex = endIndex + 1;
948
949
                    LineBreakPosition lbp = (LineBreakPosition) llPoss.getChosenPosition(i);
949
                    LineBreakPosition lbp = (LineBreakPosition) llPoss.getChosenPosition(i);
950
                    returnList.add(new KnuthBlockBox
950
                    KnuthBox newBox = new KnuthBlockBox(
951
                                   (lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
951
                            lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter, lbp, false, 1, footnoteList);
952
                                    footnoteList, lbp, false));
952
                    returnList.add(newBox);
953
954
                    startIndex = endIndex + 1;
953
                }
955
                }
954
            }
956
            }
955
        }
957
        }
Lines 1155-1163 Link Here
1155
            LineLayoutPossibilities llPoss = lineLayoutsList[p];
1157
            LineLayoutPossibilities llPoss = lineLayoutsList[p];
1156
            //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits());
1158
            //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits());
1157
            for (int i = 0; i < llPoss.getChosenLineCount(); i++) {
1159
            for (int i = 0; i < llPoss.getChosenLineCount(); i++) {
1158
                if (!((BlockLevelLayoutManager) parentLayoutManager).mustKeepTogether()
1160
                if (!((BlockLevelLayoutManager) parentLayoutManager).mustKeepTogether()) {
1159
                    && i >= fobj.getOrphans()
1160
                    && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
1161
                    // null penalty allowing a page break between lines
1161
                    // null penalty allowing a page break between lines
1162
                    returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
1162
                    returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
1163
                }
1163
                }
Lines 1182-1190 Link Here
1182
                    contentIPD
1182
                    contentIPD
1183
                        = MinOptMax.getInstance(lbp.lineWidth - lbp.difference + lbp.startIndent);
1183
                        = MinOptMax.getInstance(lbp.lineWidth - lbp.difference + lbp.startIndent);
1184
                }
1184
                }
1185
                returnList.add(new KnuthBlockBox(lbp.lineHeight, contentIPD, (lbp.ipdAdjust != 0
1185
                returnList.add(new KnuthBlockBox(lbp.lineHeight, lbp, false,
1186
                        ? lbp.lineWidth - lbp.difference : 0),
1186
                        contentIPD,
1187
                                                 lbp, false));
1187
                        (lbp.ipdAdjust != 0 ? lbp.lineWidth - lbp.difference : 0)));
1188
            }
1188
            }
1189
        }
1189
        }
1190
        return returnList;
1190
        return returnList;

Return to bug 44328