浏览代码

Bugzilla 37579: added support for footnotes in lists and table bodies (not header nor footer).

This is /not/ to be considered a final fix: similar code is duplicated over several classes (LineLayoutManager, ListItemLayoutManager and to less extent TableStepper). Footnotes should probably be handled another way.


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@660979 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Vincent Hennebert 16 年前
父节点
当前提交
3f7898c974

+ 26
- 4
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java 查看文件

@@ -26,7 +26,6 @@ import java.util.ListIterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.fo.flow.ListItem;
@@ -39,12 +38,14 @@ import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KeepUtil;
import org.apache.fop.layoutmgr.KnuthBlockBox;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPenalty;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
@@ -279,8 +280,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO;

LinkedList returnList = new LinkedList();
while ((step = getNextStep(elementLists, start, end, partialHeights))
> 0) {
while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) {
if (end[0] + 1 == elementLists[0].size()) {
keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel);
@@ -312,11 +312,33 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
int boxHeight = step - addedBoxHeight - penaltyHeight;
penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight!

// collect footnote information
// TODO this should really not be done like this. ListItemLM should remain as
// footnote-agnostic as possible
LinkedList footnoteList = null;
ListElement el;
for (int i = 0; i < elementLists.length; i++) {
for (int j = start[i]; j <= end[i]; j++) {
el = (ListElement) elementLists[i].get(j);
if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) {
if (footnoteList == null) {
footnoteList = new LinkedList();
}
footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs());
}
}
}

// add the new elements
addedBoxHeight += boxHeight;
ListItemPosition stepPosition = new ListItemPosition(this,
start[0], end[0], start[1], end[1]);
returnList.add(new KnuthBox(boxHeight, stepPosition, false));
if (footnoteList == null) {
returnList.add(new KnuthBox(boxHeight, stepPosition, false));
} else {
returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false));
}

if (addedBoxHeight < totalHeight) {
int strength = BlockLevelLayoutManager.KEEP_AUTO;
strength = Math.max(strength, keepWithNextActive);

+ 24
- 1
src/java/org/apache/fop/layoutmgr/table/ActiveCell.java 查看文件

@@ -19,12 +19,12 @@

package org.apache.fop.layoutmgr.table;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.EffRow;
@@ -32,6 +32,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthBlockBox;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPenalty;
@@ -101,6 +102,8 @@ class ActiveCell {
private int penaltyLength;
/** Value of the penalty ending this step, 0 if the step does not end on a penalty. */
private int penaltyValue;
/** List of footnotes for this step. */
private List footnoteList;
/**
* One of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
* {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE},
@@ -130,6 +133,7 @@ class ActiveCell {
this.totalLength = other.totalLength;
this.penaltyLength = other.penaltyLength;
this.penaltyValue = other.penaltyValue;
this.footnoteList = other.footnoteList;
this.condBeforeContentLength = other.condBeforeContentLength;
this.breakClass = other.breakClass;
}
@@ -293,6 +297,7 @@ class ActiveCell {
afterNextStep.penaltyValue = 0;
afterNextStep.condBeforeContentLength = 0;
afterNextStep.breakClass = Constants.EN_AUTO;
afterNextStep.footnoteList = null;
boolean breakFound = false;
boolean prevIsBox = false;
boolean boxFound = false;
@@ -322,6 +327,12 @@ class ActiveCell {
}
prevIsBox = false;
} else {
if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) {
if (afterNextStep.footnoteList == null) {
afterNextStep.footnoteList = new LinkedList();
}
afterNextStep.footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs());
}
prevIsBox = true;
boxFound = true;
afterNextStep.contentLength += el.getW();
@@ -543,6 +554,18 @@ class ActiveCell {
}
}

/**
* Adds the footnotes (if any) that are part of the next step, if this cell
* contributes content to the next step.
*
* @param footnoteList the list to which this cell must add its footnotes
*/
void addFootnotes(List footnoteList) {
if (includedInLastStep() && nextStep.footnoteList != null) {
footnoteList.addAll(nextStep.footnoteList);
}
}

int getKeepWithNextStrength() {
return keepWithNextStrength;
}

+ 10
- 1
src/java/org/apache/fop/layoutmgr/table/TableStepper.java 查看文件

@@ -33,6 +33,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.KeepUtil;
import org.apache.fop.layoutmgr.KnuthBlockBox;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
@@ -199,12 +200,14 @@ public class TableStepper {
}
}

LinkedList footnoteList = new LinkedList();
//Put all involved grid units into a list
List cellParts = new java.util.ArrayList(columnCount);
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
CellPart part = activeCell.createCellPart();
cellParts.add(part);
activeCell.addFootnotes(footnoteList);
}

//Create elements for step
@@ -217,7 +220,13 @@ public class TableStepper {
tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true);
}
lastTCPos = tcpos;
returnList.add(new KnuthBox(boxLen, tcpos, false));

// TODO TableStepper should remain as footnote-agnostic as possible
if (footnoteList.isEmpty()) {
returnList.add(new KnuthBox(boxLen, tcpos, false));
} else {
returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false));
}

int effPenaltyLen = Math.max(0, penaltyOrGlueLen);
TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM());

+ 0
- 18
test/layoutengine/disabled-testcases.xml 查看文件

@@ -97,24 +97,6 @@
<description>Space resolution does not work between footnote
regions.</description>
</testcase>
<testcase>
<name>Footnotes swallowed in lists</name>
<file>footnote_in_list.xml</file>
<description>Element lists for lists are created by combining the
element lists from list-item-label and list-item-body. The
footnotes contained in the KnuthBlockBoxes are not propagated to
the combined element list.</description>
<reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=37579</reference>
</testcase>
<testcase>
<name>Footnotes swallowed in tables</name>
<file>footnote_in_table.xml</file>
<description>Element lists for tables are created by combining the
element lists from the individual table-cells. The footnotes
contained in the KnuthBlockBoxes are not propagated to the combined
element list.</description>
<reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=37579</reference>
</testcase>
<testcase>
<name>NPE for table inside an inline</name>
<file>inline_block_nested_3.xml</file>

+ 2
- 0
test/layoutengine/standard-testcases/footnote_in_list.xml 查看文件

@@ -65,5 +65,7 @@
</fo>
<checks>
<eval expected="2" xpath="count(//footnote/block)"/>
<eval expected="1) The footnote from the normal block." xpath="//footnote/block[1]"/>
<eval expected="2) The footnote from the list." xpath="//footnote/block[2]"/>
</checks>
</testcase>

+ 125
- 0
test/layoutengine/standard-testcases/footnote_in_list_2.xml 查看文件

@@ -0,0 +1,125 @@
<?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 footnotes as descendants of list-item-body elements.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple" page-height="220pt" page-width="3in"
margin="10pt">
<fo:region-body background-color="#F0F0F0"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block>Before the list.</fo:block>
<fo:list-block provisional-distance-between-starts="1.2em" provisional-label-separation="2pt">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>–</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque<fo:footnote>
<fo:inline>(1)</fo:inline>
<fo:footnote-body>
<fo:block start-indent="0">
<fo:inline>(1)</fo:inline> First footnote from the list.</fo:block>
</fo:footnote-body>
</fo:footnote> hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices
facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl<fo:footnote>
<fo:inline>(2)</fo:inline>
<fo:footnote-body>
<fo:block start-indent="0">
<fo:inline>(2)</fo:inline> Second footnote from the list.</fo:block>
</fo:footnote-body>
</fo:footnote>.
</fo:block>
</fo:list-item-body>
</fo:list-item>
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>–</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque<fo:footnote>
<fo:inline>(3)</fo:inline>
<fo:footnote-body>
<fo:block start-indent="0">
<fo:inline>(3)</fo:inline> Third footnote from the list.</fo:block>
</fo:footnote-body>
</fo:footnote> hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices
facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl<fo:footnote>
<fo:inline>(4)</fo:inline>
<fo:footnote-body>
<fo:block start-indent="0">
<fo:inline>(4)</fo:inline> Fourth footnote from the list.</fo:block>
</fo:footnote-body>
</fo:footnote>.
</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block space-after="130pt">Before the list.</fo:block>
<fo:list-block provisional-distance-between-starts="1.2em" provisional-label-separation="2pt">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>–</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block orphans="1" widows="1">Lorem ipsum dolor sit amet, consectetuer adipiscing
elit. Pellentesque<fo:footnote>
<fo:inline>(1)</fo:inline>
<fo:footnote-body>
<fo:block start-indent="0">(1) First footnote from the list.</fo:block>
</fo:footnote-body>
</fo:footnote> hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices
facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl<fo:footnote>
<fo:inline>(2)</fo:inline>
<fo:footnote-body>
<fo:block start-indent="0">(2) Second footnote from the list.</fo:block>
</fo:footnote-body>
</fo:footnote>.
</fo:block>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<eval expected="4" xpath="count(//pageSequence[1]//footnote/block)"/>
<eval expected="(1) First footnote from the list." xpath="//pageSequence[1]//footnote/block[1]"/>
<eval expected="(2) Second footnote from the list." xpath="//pageSequence[1]//footnote/block[2]"/>
<eval expected="(3) Third footnote from the list." xpath="//pageSequence[1]//footnote/block[3]"/>
<eval expected="(4) Fourth footnote from the list." xpath="//pageSequence[1]//footnote/block[4]"/>
<eval expected="1" xpath="count(//pageSequence[2]/pageViewport[1]//footnote/block)"/>
<eval expected="(1) First footnote from the list." xpath="//pageSequence[2]/pageViewport[1]//footnote/block"/>
<eval expected="1" xpath="count(//pageSequence[2]/pageViewport[2]//footnote/block)"/>
<eval expected="(2) Second footnote from the list." xpath="//pageSequence[2]/pageViewport[2]//footnote/block"/>
</checks>
</testcase>

+ 2
- 0
test/layoutengine/standard-testcases/footnote_in_table.xml 查看文件

@@ -69,5 +69,7 @@
</fo>
<checks>
<eval expected="2" xpath="count(//footnote/block)"/>
<eval expected="1) The footnote from the normal block." xpath="//footnote/block[1]"/>
<eval expected="2) The footnote from the table." xpath="//footnote/block[2]"/>
</checks>
</testcase>

+ 185
- 0
test/layoutengine/standard-testcases/footnote_in_table_2.xml 查看文件

@@ -0,0 +1,185 @@
<?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 footnotes as descendants of table-body elements.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple" page-height="220pt" page-width="3in"
margin="10pt">
<fo:region-body background-color="#F0F0F0"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block>Before the table</fo:block>
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body border="1pt solid black">
<fo:table-row border="inherit">
<fo:table-cell border="inherit" number-rows-spanned="2">
<fo:block>Cell 1.1</fo:block>
<fo:block>Cell 1.1</fo:block>
<fo:block>Cell 1.1<fo:footnote>
<fo:inline>(2)</fo:inline>
<fo:footnote-body>
<fo:block>(2) Second footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote></fo:block>
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="inherit">
<fo:block>Cell 1.2</fo:block>
<fo:block>Cell 1.2<fo:footnote>
<fo:inline>(1)</fo:inline>
<fo:footnote-body>
<fo:block>(1) First footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote>.
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="inherit">
<fo:table-cell>
<fo:block>Cell<fo:footnote>
<fo:inline>(3)</fo:inline>
<fo:footnote-body>
<fo:block>(3) Third footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote> 2.2</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block space-after="159pt">Before the table</fo:block>
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body border="1pt solid black">
<fo:table-row border="inherit">
<fo:table-cell border="inherit" number-rows-spanned="2">
<fo:block>Cell 1.1</fo:block>
<fo:block>Cell 1.1</fo:block>
<fo:block>Cell 1.1<fo:footnote>
<fo:inline>(2)</fo:inline>
<fo:footnote-body>
<fo:block>(2) Second footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote></fo:block>
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="inherit">
<fo:block>Cell 1.2</fo:block>
<fo:block>Cell 1.2<fo:footnote>
<fo:inline>(1)</fo:inline>
<fo:footnote-body>
<fo:block>(1) First footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote>.
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="inherit">
<fo:table-cell>
<fo:block>Cell<fo:footnote>
<fo:inline>(3)</fo:inline>
<fo:footnote-body>
<fo:block>(3) Third footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote> 2.2</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block space-after="139pt">Before the table</fo:block>
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body border="1pt solid black">
<fo:table-row border="inherit">
<fo:table-cell border="inherit" number-rows-spanned="2">
<fo:block>Cell 1.1</fo:block>
<fo:block>Cell 1.1</fo:block>
<fo:block>Cell 1.1<fo:footnote>
<fo:inline>(2)</fo:inline>
<fo:footnote-body>
<fo:block>(2) Second footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote></fo:block>
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="inherit">
<fo:block>Cell 1.2</fo:block>
<fo:block>Cell 1.2<fo:footnote>
<fo:inline>(1)</fo:inline>
<fo:footnote-body>
<fo:block>(1) First footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote>.
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="inherit">
<fo:table-cell>
<fo:block>Cell<fo:footnote>
<fo:inline>(3)</fo:inline>
<fo:footnote-body>
<fo:block>(3) Third footnote from the table.</fo:block>
</fo:footnote-body>
</fo:footnote> 2.2</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<eval expected="3" xpath="count(//pageSequence[1]//footnote/block)"/>
<eval expected="(1) First footnote from the table." xpath="//pageSequence[1]//footnote/block[1]"/>
<eval expected="(2) Second footnote from the table." xpath="//pageSequence[1]//footnote/block[2]"/>
<eval expected="(3) Third footnote from the table." xpath="//pageSequence[1]//footnote/block[3]"/>

<eval expected="1" xpath="count(//pageSequence[2]/pageViewport[1]//footnote/block)"/>
<eval expected="(1) First footnote from the table." xpath="//pageSequence[2]/pageViewport[1]//footnote/block[1]"/>
<eval expected="2" xpath="count(//pageSequence[2]/pageViewport[2]//footnote/block)"/>
<eval expected="(2) Second footnote from the table." xpath="//pageSequence[2]/pageViewport[2]//footnote/block[1]"/>
<eval expected="(3) Third footnote from the table." xpath="//pageSequence[2]/pageViewport[2]//footnote/block[2]"/>

<eval expected="2" xpath="count(//pageSequence[3]/pageViewport[1]//footnote/block)"/>
<eval expected="(1) First footnote from the table." xpath="//pageSequence[3]/pageViewport[1]//footnote/block[1]"/>
<eval expected="(2) Second footnote from the table." xpath="//pageSequence[3]/pageViewport[1]//footnote/block[2]"/>
<eval expected="1" xpath="count(//pageSequence[3]/pageViewport[2]//footnote/block)"/>
<eval expected="(3) Third footnote from the table." xpath="//pageSequence[3]/pageViewport[2]//footnote/block[1]"/>
</checks>
</testcase>

正在加载...
取消
保存