ASF Bugzilla – Attachment 26851 Details for
Bug 44328
[PATCH] orphans/widows not respected in some cases
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
updated patch, addresses the described issue with nested tables/lists
b44328.patch (text/plain), 46.63 KB, created by
Andreas L. Delmelle
on 2011-04-04 11:28:29 UTC
(
hide
)
Description:
updated patch, addresses the described issue with nested tables/lists
Filename:
MIME Type:
Creator:
Andreas L. Delmelle
Created:
2011-04-04 11:28:29 UTC
Size:
46.63 KB
patch
obsolete
>Index: test/layoutengine/standard-testcases/block_list-block_orphans_widows.xml >=================================================================== >--- test/layoutengine/standard-testcases/block_list-block_orphans_widows.xml (revision ) >+++ test/layoutengine/standard-testcases/block_list-block_orphans_widows.xml (revision ) >@@ -0,0 +1,128 @@ >+<?xml version="1.0" encoding="UTF-8"?> >+<!-- >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+--> >+<!-- $Id$ --> >+<testcase> >+ <info> >+ <p> >+ This test checks the behavior of the "orphans" and "widows" properties >+ in case list-blocks are nested in blocks. >+ </p> >+ </info> >+ <fo> >+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> >+ <fo:layout-master-set> >+ <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in"> >+ <fo:region-body /> >+ </fo:simple-page-master> >+ </fo:layout-master-set> >+ <fo:page-sequence master-reference="normal"> >+ <fo:flow flow-name="xsl-region-body"> >+ <fo:block id="block-1"> >+ <!-- Check that the last list-item is not unnecessarily kept together. >+ The inner block's widows constraint causes the list-layout code >+ to generate a merged last box, which as a single box, satisfies >+ the containing block's constraint. >+ --> >+ <fo:list-block> >+ <fo:list-item> >+ <fo:list-item-label><fo:block /></fo:list-item-label> >+ <fo:list-item-body> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:list-item-body> >+ </fo:list-item> >+ <fo:list-item> >+ <fo:list-item-label><fo:block /></fo:list-item-label> >+ <fo:list-item-body> >+ <fo:block> >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ </fo:block> >+ </fo:list-item-body> >+ </fo:list-item> >+ <fo:list-item> >+ <fo:list-item-label><fo:block /></fo:list-item-label> >+ <fo:list-item-body> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:list-item-body> >+ </fo:list-item> >+ </fo:list-block> >+ </fo:block> >+ <fo:block id="block-2" break-before="page"> >+ <!-- Check that the first list-item is not unnecessarily kept together. >+ The inner block's widows constraint causes the list-layout code >+ to generate a merged first box, which as a single box, satisfies >+ the containing block's constraint. >+ --> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ <fo:block id="block-2a"> >+ <fo:list-block> >+ <fo:list-item> >+ <fo:list-item-label><fo:block /></fo:list-item-label> >+ <fo:list-item-body> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:list-item-body> >+ </fo:list-item> >+ <fo:list-item> >+ <fo:list-item-label><fo:block /></fo:list-item-label> >+ <fo:list-item-body> >+ <fo:block> >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ </fo:block> >+ </fo:list-item-body> >+ </fo:list-item> >+ </fo:list-block> >+ </fo:block> >+ </fo:block> >+ </fo:flow> >+ </fo:page-sequence> >+ </fo:root> >+ </fo> >+ <checks> >+ <eval expected="10" xpath="count((//page)[1]//lineArea)" /> >+ <eval expected="2" xpath="count((//page)[2]//lineArea)" /> >+ <eval expected="10" xpath="count((//page)[3]//lineArea)" /> >+ <eval expected="6" xpath="count((//page)[4]//lineArea)" /> >+ </checks> >+</testcase> >Index: test/layoutengine/standard-testcases/block_table_orphans_widows.xml >=================================================================== >--- test/layoutengine/standard-testcases/block_table_orphans_widows.xml (revision ) >+++ test/layoutengine/standard-testcases/block_table_orphans_widows.xml (revision ) >@@ -0,0 +1,119 @@ >+<?xml version="1.0" encoding="UTF-8"?> >+<!-- >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+--> >+<!-- $Id$ --> >+<testcase> >+ <info> >+ <p> >+ This test checks the behavior of the "orphans" and "widows" properties >+ in case tables are nested in blocks. >+ </p> >+ </info> >+ <fo> >+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> >+ <fo:layout-master-set> >+ <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in"> >+ <fo:region-body /> >+ </fo:simple-page-master> >+ </fo:layout-master-set> >+ <fo:page-sequence master-reference="normal"> >+ <fo:flow flow-name="xsl-region-body"> >+ <fo:block id="block-1"> >+ <!-- Check that the last row is not unnecessarily kept together. >+ The inner block's widows constraint causes the table-layout code >+ to generate a merged last box, which as a single box, satisfies >+ the containing block's constraint. >+ --> >+ <fo:table table-layout="fixed" width="100%"> >+ <fo:table-column column-width="proportional-column-width(1)" /> >+ <fo:table-body> >+ <fo:table-cell starts-row="true" ends-row="true"> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:table-cell> >+ <fo:table-cell starts-row="true" ends-row="true"> >+ <fo:block> >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ </fo:block> >+ </fo:table-cell> >+ <fo:table-cell starts-row="true" ends-row="true"> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:table-cell> >+ </fo:table-body> >+ </fo:table> >+ </fo:block> >+ <fo:block id="block-2" break-before="page"> >+ <!-- Check that the first row is not unnecessarily kept together. >+ The inner block's orphans constraint causes the table-layout code >+ to generate a merged first box, which as a single box, satisfies >+ the containing block's constraint. >+ --> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ <fo:block id="block-2a"> >+ <fo:table table-layout="fixed" width="100%"> >+ <fo:table-column column-width="proportional-column-width(1)" /> >+ <fo:table-body> >+ <fo:table-cell starts-row="true" ends-row="true"> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:table-cell> >+ <fo:table-cell starts-row="true" ends-row="true"> >+ <fo:block> >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ </fo:block> >+ </fo:table-cell> >+ </fo:table-body> >+ </fo:table> >+ </fo:block> >+ </fo:block> >+ </fo:flow> >+ </fo:page-sequence> >+ </fo:root> >+ </fo> >+ <checks> >+ <eval expected="10" xpath="count((//page)[1]//lineArea)" /> >+ <eval expected="2" xpath="count((//page)[2]//lineArea)" /> >+ <eval expected="10" xpath="count((//page)[3]//lineArea)" /> >+ <eval expected="6" xpath="count((//page)[4]//lineArea)" /> >+ </checks> >+</testcase> >Index: test/layoutengine/standard-testcases/block_widows.xml >=================================================================== >--- test/layoutengine/standard-testcases/block_widows.xml (revision ) >+++ test/layoutengine/standard-testcases/block_widows.xml (revision ) >@@ -0,0 +1,143 @@ >+<?xml version="1.0" encoding="UTF-8"?> >+<!-- >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+--> >+<!-- $Id$ --> >+<testcase> >+ <info> >+ <p> >+ This test checks the default behavior of the "widows" property. >+ </p> >+ </info> >+ <fo> >+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> >+ <fo:layout-master-set> >+ <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in"> >+ <fo:region-body /> >+ </fo:simple-page-master> >+ </fo:layout-master-set> >+ <fo:page-sequence master-reference="normal"> >+ <fo:flow flow-name="xsl-region-body"> >+ <fo:block id="block-1"> >+ <!-- Basic test: simple paragraph generating 11 lines. >+ 2 last lines should be kept together due to initial >+ value for widows >+ --> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ fermentum tempor nunc. Class aptent >+ taciti sociosqu ad litora torquent per >+ </fo:block> >+ <fo:block id="block-2" break-before="page"> >+ <!-- Basic test: simple paragraph generating 11 lines, followed by >+ another block. >+ A break between lines 10 and 11 is allowed. >+ --> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ fermentum tempor nunc. Class aptent >+ taciti sociosqu ad litora torquent per >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:block> >+ <fo:block id="block-3" break-before="page"> >+ <!-- Basic test: 1 paragraph consisting of 11 single-line subparagraphs. >+ Last 2 lines of the main paragraph should be kept together due to >+ initial value for widows. >+ --> >+ <fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ </fo:block> >+ </fo:block> >+ <fo:block id="block-4" break-before="page"> >+ <!-- Special case: linefeed-treatment="preserve" (see Bugzilla 44328) --> >+ <fo:block linefeed-treatment="preserve">Lorem ipsum >+ dolor sit amet, >+ consectetur >+ adipiscing elit. >+ Cras placerat, >+ lectus vel >+ iaculis euismod, >+ ipsum enim >+ dapibus urna, >+ eu pellentesque >+ velit dolor</fo:block> >+ </fo:block> >+ <fo:block id="block-5" break-before="page"> >+ <!-- Special case: 1 paragraph with 10 lines, and 1 with 1. >+ Last 2 lines of the first paragraph should be kept >+ together with the only line of the second due to initial >+ value of widows on the outer block. >+ --> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ fermentum tempor nunc. Class aptent >+ </fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ </fo:block> >+ </fo:flow> >+ </fo:page-sequence> >+ </fo:root> >+ </fo> >+ <checks> >+ <eval expected="9" xpath="count((//page)[1]//lineArea)" /> >+ <eval expected="2" xpath="count((//page)[2]//lineArea)" /> >+ <eval expected="10" xpath="count((//page)[3]//lineArea)" /> >+ <eval expected="5" xpath="count((//page)[4]//lineArea)" /> >+ <eval expected="9" xpath="count((//page)[5]//lineArea)" /> >+ <eval expected="2" xpath="count((//page)[6]//lineArea)" /> >+ <eval expected="9" xpath="count((//page)[7]//lineArea)" /> >+ <eval expected="2" xpath="count((//page)[8]//lineArea)" /> >+ <eval expected="8" xpath="count((//page)[9]//lineArea)" /> >+ <eval expected="3" xpath="count((//page)[10]//lineArea)" /> >+ </checks> >+</testcase> >\ No newline at end of file >Index: test/layoutengine/standard-testcases/block_orphans.xml >=================================================================== >--- test/layoutengine/standard-testcases/block_orphans.xml (revision ) >+++ test/layoutengine/standard-testcases/block_orphans.xml (revision ) >@@ -0,0 +1,167 @@ >+<?xml version="1.0" encoding="UTF-8"?> >+<!-- >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+--> >+<!-- $Id$ --> >+<testcase> >+ <info> >+ <p> >+ This test checks the default behavior of the "orphans" property. >+ </p> >+ </info> >+ <fo> >+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> >+ <fo:layout-master-set> >+ <fo:simple-page-master master-name="normal" page-width="3in" page-height="2in"> >+ <fo:region-body /> >+ </fo:simple-page-master> >+ </fo:layout-master-set> >+ <fo:page-sequence master-reference="normal"> >+ <fo:flow flow-name="xsl-region-body"> >+ <fo:block id="block-1" break-before="page"> >+ <!-- Basic test: 1 paragraph with 9 lines and 1 with 4. >+ All 4 lines of the second paragraph should be kept >+ together due to initial value for orphans. >+ --> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ </fo:block> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ </fo:block> >+ <fo:block id="block-2" break-before="page"> >+ <!-- Basic test: 1 block with 9 lines and 1 paragraph with 4 lines. >+ A break after the first line of the second paragraph is allowed. >+ --> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ </fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ </fo:block> >+ <fo:block id="block-3" break-before="page"> >+ <!-- Basic test: 1 regular paragraph of 9 lines followed by 1 consisting >+ of 4 single-line subparagraphs. >+ All 4 lines of the second paragraph should be kept together due >+ to initial value for orphans. >+ --> >+ <fo:block id="block-3a"> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ </fo:block> >+ <fo:block id="block-3b"> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block>Lorem ipsum</fo:block> >+ </fo:block> >+ </fo:block> >+ <fo:block id="block-4" break-before="page"> >+ <!-- Special case: linefeed-treatment="preserve" (see Bugzilla 44328) --> >+ <fo:block> >+ Lorem ipsum dolor sit amet, consectetur >+ adipiscing elit. Cras placerat, lectus vel >+ iaculis euismod, ipsum enim dapibus >+ urna, eu pellentesque velit dolor ac >+ purus. Maecenas vitae pulvinar turpis. >+ Duis venenatis tincidunt velit, fringilla >+ dignissim sapien faucibus vel. Quisque >+ placerat ornare consectetur. Aenean >+ dui tortor, tempor ut convallis in, >+ </fo:block> >+ <fo:block linefeed-treatment="preserve">Lorem ipsum >+ dolor sit amet, >+ consectetur >+ velit dolor</fo:block> >+ </fo:block> >+ <fo:block id="block-5" break-before="page" widows="1"> >+ <!-- Last but not least, demonstrate peculiar side-effect in case >+ of convoluted nesting... >+ Even though widows would allow a break before the last line, >+ all 10 last lines are moved to the next page due to stacked >+ orphans constraints >+ --> >+ <fo:block id="level-1">Lorem ipsum >+ <fo:block>Lorem ipsum</fo:block> >+ <fo:block id="level-2">Lorem ipsum >+ <fo:block id="level-3">Lorem ipsum >+ <fo:block id="level-4">Lorem ipsum >+ <fo:block id="level-5">Lorem ipsum >+ <fo:block id="level-6">Lorem ipsum >+ <fo:block id="level-7">Lorem ipsum >+ <fo:block id="level-8">Lorem ipsum >+ <fo:block id="level-9">Lorem ipsum >+ <fo:block id="level-10">Lorem ipsum >+ <fo:block id="level-11"> >+ Lorem ipsum >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:block> >+ </fo:flow> >+ </fo:page-sequence> >+ </fo:root> >+ </fo> >+ <checks> >+ <eval expected="9" xpath="count((//page)[1]//lineArea)" /> >+ <eval expected="4" xpath="count((//page)[2]//lineArea)" /> >+ <eval expected="10" xpath="count((//page)[3]//lineArea)" /> >+ <eval expected="3" xpath="count((//page)[4]//lineArea)" /> >+ <eval expected="9" xpath="count((//page)[5]//lineArea)" /> >+ <eval expected="4" xpath="count((//page)[6]//lineArea)" /> >+ <eval expected="9" xpath="count((//page)[7]//lineArea)" /> >+ <eval expected="4" xpath="count((//page)[8]//lineArea)" /> >+ <eval expected="2" xpath="count((//page)[9]//lineArea)" /> >+ <eval expected="10" xpath="count((//page)[10]//lineArea)" /> >+ </checks> >+</testcase> >Index: src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java (revision 1073116) >+++ src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java (revision ) >@@ -66,6 +66,9 @@ > private MinOptMax effSpaceBefore; > private MinOptMax effSpaceAfter; > >+ private int orphans = 2; >+ private int widows = 2; >+ > /** > * Creates a new BlockLayoutManager. > * @param inBlock the block FO object to create the layout manager for. >@@ -97,6 +100,8 @@ > .getOptimum(this).getLength().getValue(this); > adjustedSpaceAfter = fo.getCommonMarginBlock().spaceAfter.getSpace() > .getOptimum(this).getLength().getValue(this); >+ orphans = fo.getOrphans(); >+ widows = fo.getWidows(); > } > > /** {@inheritDoc} */ >@@ -110,10 +115,42 @@ > public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack, > Position restartPosition, LayoutManager restartAtLM) { > resetSpaces(); >- return super.getNextKnuthElements( >+ >+ List<ListElement> contentList = super.getNextKnuthElements( > context, alignment, lmStack, restartPosition, restartAtLM); >+ >+ if (!this.hasNextChildLM()) { >+ // handle widows >+ int lineCount = 0, boxCount = 0, index = contentList.size(); >+ ListElement current; >+ for (ListIterator<ListElement> it = contentList.listIterator(contentList.size()); >+ it.hasPrevious();) { >+ current = it.previous(); >+ index--; >+ if (current.isBox() && !((KnuthBox) current).isAuxiliary()) { >+ boxCount++; >+ // non-auxiliary box => increase lineCount >+ if (current instanceof KnuthBlockBox) { >+ lineCount += ((KnuthBlockBox) current).getLineCount(); >+ } else { >+ // assume one line >+ lineCount++; >- } >+ } >+ if (lineCount >= widows) { >+ break; >+ } >+ } >+ } >+ // if the sublist only consists of boxes, nothing to remove >+ if (index <= (contentList.size() - boxCount)) { >+ ElementListUtils.removeLegalBreaks( >+ contentList.subList(index, contentList.size())); >+ } >+ } > >+ return contentList; >+ } >+ > /** > * Overridden to take into account that the childLM may be the block's > * {@link LineLayoutManager}. >@@ -132,25 +169,77 @@ > // nop; will have been properly set by makeChildLayoutContext() > } > >- if (childLM == this.childLMs.get(0)) { >+ boolean isFirst = childLM == this.childLMs.get(0); >+ if (isFirst) { > childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); > //Handled already by the parent (break collapsing, see above) > } > >+ List<ListElement> childElements; > if (lmStack == null) { >- return childLM.getNextKnuthElements(childLC, alignment); >+ childElements = childLM.getNextKnuthElements(childLC, alignment); > } else { > if (childLM instanceof LineLayoutManager) { > assert (restartPosition instanceof LeafPosition); >- return ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment, >+ childElements >+ = ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment, >- (LeafPosition) restartPosition); >+ (LeafPosition) restartPosition); > } else { >- return childLM.getNextKnuthElements(childLC, alignment, >+ childElements = childLM.getNextKnuthElements(childLC, alignment, > lmStack, restartPosition, restartAtLM); > } > } >+ >+ if (isFirst) { >+ // handle orphans >+ int lineCount = 0, boxCount = 0, endIndex = 0; >+ ListElement current; >+ for (ListIterator<ListElement> it = childElements.listIterator(); it.hasNext();) { >+ current = it.next(); >+ endIndex++; >+ if (current.isBox() && !((KnuthBox) current).isAuxiliary()) { >+ boxCount++; >+ // non-auxiliary box => increase lineCount >+ if (current instanceof KnuthBlockBox) { >+ lineCount += ((KnuthBlockBox) current).getLineCount(); >+ } else { >+ // assume one line >+ lineCount++; >- } >+ } >+ if (lineCount >= orphans) { >+ break; >+ } >+ } >+ } >+ // if the sublist only consists of boxes, nothing to remove >+ if (endIndex > boxCount) { >+ ElementListUtils.removeLegalBreaks(childElements.subList(0, endIndex)); >+ } >+ } > >+ return childElements; >+ } >+ >+ /** >+ * Overridden to deal with a special case for the "orphans" property. >+ * {@inheritDoc} >+ */ >+ @Override >+ protected void addInBetweenBreak(List<ListElement> contentList, >+ LayoutContext parentLC, LayoutContext childLC) { >+ >+ if (this.childLMs.size() > 1 >+ && this.curChildLM == this.childLMs.get(1)) { >+ // special case: second childLM; if the first childLM did not produce enough >+ // lines to satisfy this LM's orphans constraint, avoid adding a break possibility >+ if (ElementListUtils.getLineCount(contentList) < orphans) { >+ return; >+ } >+ } >+ >+ super.addInBetweenBreak(contentList, parentLC, childLC); >+ } >+ > private void resetSpaces() { > this.discardBorderBefore = false; > this.discardBorderAfter = false; >Index: src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (revision 1088079) >+++ src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (revision ) >@@ -918,10 +918,7 @@ > for (int i = 0; > i < llPoss.getChosenLineCount(); > i++) { >- if (returnList.size() > 0 >- && i > 0 //if i==0 break generated above already >- && i >= fobj.getOrphans() >- && i <= llPoss.getChosenLineCount() - fobj.getWidows()) { >+ if (returnList.size() > 0 && i > 0) { > // penalty allowing a page break between lines > Keep keep = getKeepTogether(); > returnList.add(new BreakElement( >Index: src/java/org/apache/fop/layoutmgr/table/TableStepper.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/table/TableStepper.java (revision 1083863) >+++ src/java/org/apache/fop/layoutmgr/table/TableStepper.java (revision ) >@@ -181,6 +181,7 @@ > TableContentPosition lastTCPos = null; > LinkedList returnList = new LinkedList(); > int laststep = 0; >+ int stepLines; > int step = getFirstStep(); > do { > int maxRemainingHeight = getMaxRemainingHeight(); >@@ -201,10 +202,15 @@ > LinkedList footnoteList = new LinkedList(); > //Put all involved grid units into a list > List cellParts = new java.util.ArrayList(columnCount); >+ stepLines = 0; > for (Iterator iter = activeCells.iterator(); iter.hasNext();) { > ActiveCell activeCell = (ActiveCell) iter.next(); > CellPart part = activeCell.createCellPart(); > cellParts.add(part); >+ int partLines = part.getLineCount(); >+ if (partLines > stepLines) { >+ stepLines = partLines; >+ } > activeCell.addFootnotes(footnoteList); > } > >@@ -219,12 +225,15 @@ > } > lastTCPos = tcpos; > >+ KnuthBlockBox newBox; > // TODO TableStepper should remain as footnote-agnostic as possible > if (footnoteList.isEmpty()) { >- returnList.add(new KnuthBox(boxLen, tcpos, false)); >+ newBox = new KnuthBlockBox(boxLen, tcpos, false); > } else { >- returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false)); >+ newBox = new KnuthBlockBox(boxLen, footnoteList, tcpos, false); > } >+ newBox.setLineCount(stepLines); >+ returnList.add(newBox); > > int effPenaltyLen = Math.max(0, penaltyOrGlueLen); > TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM()); >Index: src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java (revision 893238) >+++ src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java (revision ) >@@ -19,6 +19,7 @@ > > package org.apache.fop.layoutmgr; > >+import java.util.Collections; > import java.util.LinkedList; > import java.util.List; > >@@ -35,54 +36,66 @@ > * it isn't possible to get the opt value stored in a MinOptMax object. > */ > private int bpd; >- private List footnoteList; >+ private List<FootnoteBodyLayoutManager> footnoteList; > /** List of Knuth elements. This is a list of LinkedList elements. */ >- private List elementLists = null; >+ private List<List<ListElement>> elementLists; >+ private int lineCount; > > /** > * Creates a new box. > * > * @param width block progression dimension of this box >+ * @param pos the Position stored in this box >+ * @param auxiliary is this box auxiliary? >+ */ >+ public KnuthBlockBox(int width, Position pos, boolean auxiliary) { >+ super(width, pos, auxiliary); >+ // assume one line by default, if the box is not auxiliary >+ this.lineCount = (auxiliary ? 0 : 1); >+ } >+ >+ /** >+ * Creates a new box. >+ * >+ * @param width block progression dimension of this box > * @param range min, opt, max inline progression dimension of this box > * @param bpdim natural width of the line represented by this box. > * @param pos the Position stored in this box > * @param auxiliary is this box auxiliary? > */ > public KnuthBlockBox(int width, MinOptMax range, int bpdim, Position pos, boolean auxiliary) { >- super(width, pos, auxiliary); >- ipdRange = range; >- bpd = bpdim; >- footnoteList = new LinkedList(); >+ this(width, pos, auxiliary); >+ this.ipdRange = range; >+ this.bpd = bpdim; > } > > /** > * Creates a new box. > * > * @param width block progression dimension of this box >- * @param list footnotes cited by elements in this box. The list contains the corresponding >- * FootnoteBodyLayoutManagers >+ * @param footnoteList footnotes cited by elements in this box. >+ * The list contains the corresponding FootnoteBodyLayoutManagers > * @param pos the Position stored in this box > * @param auxiliary is this box auxiliary? > */ >- public KnuthBlockBox(int width, List list, Position pos, boolean auxiliary) { >- super(width, pos, auxiliary); >- ipdRange = MinOptMax.ZERO; >- bpd = 0; >- footnoteList = new LinkedList(list); >+ public KnuthBlockBox(int width, List footnoteList, Position pos, boolean auxiliary) { >+ this(width, MinOptMax.ZERO, 0, pos, auxiliary); >+ this.footnoteList = new LinkedList<FootnoteBodyLayoutManager>(footnoteList); > } > > /** > * @return the LMs for the footnotes cited in this box. > */ >- public List getFootnoteBodyLMs() { >- return footnoteList; >+ public List<FootnoteBodyLayoutManager> getFootnoteBodyLMs() { >+ return (footnoteList == null >+ ? Collections.<FootnoteBodyLayoutManager>emptyList() : footnoteList); > } > > /** > * @return true if this box contains footnote citations. > */ > public boolean hasAnchors() { >- return (footnoteList.size() > 0); >+ return (footnoteList != null && footnoteList.size() > 0); > } > > /** >@@ -92,7 +105,7 @@ > */ > public void addElementList(List list) { > if (elementLists == null) { >- elementLists = new LinkedList(); >+ elementLists = new LinkedList<List<ListElement>>(); > } > elementLists.add(list); > } >@@ -122,4 +135,21 @@ > public int getBPD() { > return bpd; > } >+ >+ /** >+ * Returns the (maximum) number of lines in this box. >+ * @return the maximum number of lines contained in this box. >+ */ >+ public int getLineCount() { >+ return lineCount; >-} >+ } >+ >+ /** >+ * Sets the maximum number of lines in this box. >+ * @param lineCount the number of lines >+ */ >+ public void setLineCount(int lineCount) { >+ this.lineCount = lineCount; >+ } >+ >+} >Index: src/java/org/apache/fop/layoutmgr/table/CellPart.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/table/CellPart.java (revision 990144) >+++ src/java/org/apache/fop/layoutmgr/table/CellPart.java (revision ) >@@ -20,6 +20,7 @@ > package org.apache.fop.layoutmgr.table; > > import org.apache.fop.fo.flow.table.PrimaryGridUnit; >+import org.apache.fop.layoutmgr.ElementListUtils; > > /** > * Represents a non-divisible part of a grid unit. Used by the table stepper. >@@ -117,6 +118,10 @@ > return condAfterContentLength; > } > >+ int getLineCount() { >+ return ElementListUtils.getLineCount(pgu.getElements().subList(start, end + 1)); >+ } >+ > /** {@inheritDoc} */ > public String toString() { > StringBuffer sb = new StringBuffer("Part: "); >Index: src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java (revision 1069941) >+++ src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java (revision ) >@@ -316,6 +316,7 @@ > // footnote-agnostic as possible > LinkedList<FootnoteBodyLayoutManager> footnoteList = null; > ListElement el; >+ int stepLines = 0; > for (int i = 0; i < elementLists.length; i++) { > for (int j = start[i]; j <= end[i]; j++) { > el = (ListElement) elementLists[i].get(j); >@@ -326,17 +327,25 @@ > footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); > } > } >+ int lineCount = ElementListUtils.getLineCount( >+ elementLists[i].subList(start[i], end[i] + 1)); >+ if (lineCount > stepLines) { >+ stepLines = lineCount; >- } >+ } >+ } > > // add the new elements > addedBoxHeight += boxHeight; > ListItemPosition stepPosition = new ListItemPosition(this, > start[0], end[0], start[1], end[1]); >+ KnuthBlockBox newBox; > if (footnoteList == null) { >- returnList.add(new KnuthBox(boxHeight, stepPosition, false)); >+ newBox = new KnuthBlockBox(boxHeight, stepPosition, false); > } else { >- returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false)); >+ newBox = new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false); > } >+ newBox.setLineCount(stepLines); >+ returnList.add(newBox); > > if (addedBoxHeight < totalHeight) { > Keep keep = keepWithNextActive.compare(getKeepTogether()); >@@ -694,6 +703,5 @@ > body.reset(); > } > >- > } > >Index: src/java/org/apache/fop/layoutmgr/KnuthPenalty.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/KnuthPenalty.java (revision 1079013) >+++ src/java/org/apache/fop/layoutmgr/KnuthPenalty.java (revision ) >@@ -46,6 +46,9 @@ > /** Dummy, zero-width penalty */ > public static final KnuthPenalty DUMMY_ZERO_PENALTY > = new KnuthPenalty(0, 0, false, null, true); >+ /** Dummy break inhibitor */ >+ public static final KnuthPenalty DUMMY_INFINITE_PENALTY >+ = new KnuthPenalty(0, KnuthElement.INFINITE, false, null, true); > > private int penalty; > private boolean penaltyFlagged; >Index: src/java/org/apache/fop/layoutmgr/ElementListUtils.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/ElementListUtils.java (revision 1056513) >+++ src/java/org/apache/fop/layoutmgr/ElementListUtils.java (revision ) >@@ -133,6 +133,87 @@ > } > > /** >+ * Removes all legal break points from the given {@code List<ListElement>}. >+ * That is, this method:<br/> >+ * <ul> >+ * <li>removes penalties in between two boxes</li> >+ * <li>converts other penalties to inhibit breaks</li> >+ * <li>converts glues following a box into auxiliary boxes >+ * or penalty-glue sequences</li> >+ * </ul> >+ * <br/> >+ * <em>Note: leading glues will not be treated, as it is assumed nothing precedes >+ * the first element of the given list. Similarly, trailing penalties would just be set >+ * to {@link KnuthElement#INFINITE}, as there is never a following box.<br/> >+ * Care should be taken to provide as much context elements as required. Ideally, the >+ * list should start with a box and end with a box or glue.</em> >+ * >+ * @param elements the element list from which the breaks will be removed >+ */ >+ public static void removeLegalBreaks(List<ListElement> elements) { >+ >+ ListElement current; >+ boolean previousIsBox = false; >+ >+ for (ListIterator<ListElement> it = elements.listIterator(); it.hasNext();) { >+ >+ current = it.next(); >+ >+ if (current.isBox()) { >+ previousIsBox = true; >+ continue; >+ } else if (current.isGlue() && previousIsBox) { >+ KnuthGlue glue = (KnuthGlue)current; >+ if (glue.getStretch() == 0 && glue.getShrink() == 0) { >+ // non-stretchable glue => replace with a box of the same width >+ it.set(new KnuthBox(glue.getWidth(), glue.getPosition(), true)); >+ } else { >+ // stretchable glue => add break-inhibitor >+ it.previous(); >+ it.add(KnuthPenalty.DUMMY_INFINITE_PENALTY); >+ it.next(); >+ } >+ } else if (current.isPenalty() || current instanceof BreakElement >+ && !current.isForcedBreak()) { >+ boolean nextIsBox = (it.hasNext() && it.next().isBox()); >+ it.previous(); >+ if (previousIsBox && nextIsBox) { >+ // penalty or BreakElement in between boxes => remove >+ it.previous(); >+ it.remove(); >+ } else { >+ if (current.isPenalty()) { >+ ((KnuthPenalty)current).setPenalty(KnuthElement.INFINITE); >+ } else { >+ ((BreakElement)current).setPenaltyValue(KnuthElement.INFINITE); >+ } >+ } >+ } >+ previousIsBox = false; >+ } >+ } >+ >+ /** >+ * Obtains the (maximum) number of lines in the given list. >+ * @param elements the list to count the lines for >+ * @return the number of lines >+ */ >+ public static int getLineCount(List<ListElement> elements) { >+ int lineCount = 0; >+ for (ListElement current : elements) { >+ if (current.isBox() && !((KnuthBox) current).isAuxiliary()) { >+ if (current instanceof KnuthBlockBox) { >+ lineCount += ((KnuthBlockBox) current).getLineCount(); >+ } else { >+ // assume one line >+ lineCount++; >+ } >+ } >+ } >+ return lineCount; >+ } >+ >+ /** > * Calculates the content length of the given element list. Warning: It doesn't take any > * stretch and shrink possibilities into account. > * @param elems the element list
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 44328
:
21452
|
26800
|
26801
|
26807
|
26813
|
26820
|
26842
|
26843
|
26845
|
26846
|
26851
|
26852
|
27055
|
27066