Procházet zdrojové kódy

Fixing a problem with disappearing footnotes inside inlines when hyphenation is enabled, and with disappearing footnotes whose inline child can be hyphenated (quite unlikely, but you never know ...).

As the FootnoteLM was completely "bypassed", it could not add the anchor in the getChangedKnuthElement() phase.
Testcase updated with an example of the "hyphenated inline child" case.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@538198 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_94
Luca Furini před 17 roky
rodič
revize
29ea9c1b10

+ 71
- 54
src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java Zobrazit soubor

@@ -26,19 +26,20 @@ import java.util.ListIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.flow.Footnote;
import org.apache.fop.layoutmgr.AbstractLayoutManager;
import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthSequence;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.PositionIterator;

/**
* Layout manager for fo:footnote.
*/
public class FootnoteLayoutManager extends AbstractLayoutManager
implements InlineLevelLayoutManager {
public class FootnoteLayoutManager extends InlineStackingLayoutManager {

/**
* logging instance
@@ -72,13 +73,10 @@ public class FootnoteLayoutManager extends AbstractLayoutManager
/** @see org.apache.fop.layoutmgr.LayoutManager */
public LinkedList getNextKnuthElements(LayoutContext context,
int alignment) {
// this is the only method that must be implemented:
// all other methods will never be called, as the returned elements
// contain Positions created by the citationLM, so its methods will
// be called instead

// set the citationLM parent to be this LM's parent
citationLM.setParent(getParent());
// for the moment, this LM is set as the citationLM's parent
// later on, when this LM will have nothing more to do, the citationLM's parent
// will be set to the fotnoteLM's parent
citationLM.setParent(this);
citationLM.initialize();
bodyLM.setParent(this);
bodyLM.initialize();
@@ -104,22 +102,82 @@ public class FootnoteLayoutManager extends AbstractLayoutManager

addAnchor(returnedList);

// "wrap" the Position stored in each list inside returnedList
ListIterator listIterator = returnedList.listIterator();
ListIterator elementIterator = null;
KnuthSequence list = null;
ListElement element = null;
while (listIterator.hasNext()) {
list = (KnuthSequence) listIterator.next();
elementIterator = list.listIterator();
while (elementIterator.hasNext()) {
element = (KnuthElement) elementIterator.next();
element.setPosition(notifyPos(new NonLeafPosition(this, element.getPosition())));
}
}

return returnedList;
}

/**
* @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int)
*/
public LinkedList getChangedKnuthElements(List oldList,
int alignment) {
LinkedList returnedList = super.getChangedKnuthElements(oldList, alignment);
addAnchor(returnedList);
return returnedList;
}


/**
* @see org.apache.fop.layoutmgr.LayoutManager#addAreas(PositionIterator posIter, LayoutContext context);
*/
public void addAreas(PositionIterator posIter, LayoutContext context) {
// "Unwrap" the NonLeafPositions stored in posIter and put
// them in a new list, that will be given to the citationLM
LinkedList positionList = new LinkedList();
NonLeafPosition pos = null;
while (posIter.hasNext()) {
pos = (NonLeafPosition) posIter.next();
if (pos != null && pos.getPosition() != null) {
positionList.add(pos.getPosition());
}
}
// FootnoteLM does not create any area,
// so the citationLM child will add directly to the FootnoteLM parent area
citationLM.setParent(getParent());
// make the citationLM add its areas
LayoutContext childContext = new LayoutContext(context);
StackingIter childPosIter = new StackingIter(positionList.listIterator());
LayoutManager childLM;
while ((childLM = childPosIter.getNextChildLM()) != null) {
childLM.addAreas(childPosIter, childContext);
childContext.setLeadingSpace(childContext.getTrailingSpace());
childContext.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
}
}

/**
* Find the last box in the sequence, and add a reference to the FootnoteBodyLM
* @param citationList the list of elements representing the footnote citation
*/
private void addAnchor(LinkedList citationList) {
// find the last box in the sequence, and add a reference
// to the FootnoteBodyLM
KnuthInlineBox lastBox = null;
// the list of elements is searched backwards, until we find a box
ListIterator citationIterator = citationList.listIterator(citationList.size());
while (citationIterator.hasPrevious() && lastBox == null) {
Object obj = citationIterator.previous();
if (obj instanceof KnuthElement) {
// obj is an element
KnuthElement element = (KnuthElement)obj;
if (element instanceof KnuthInlineBox) {
lastBox = (KnuthInlineBox) element;
}
} else {
// obj is a sequence of elements
KnuthSequence seq = (KnuthSequence)obj;
ListIterator nestedIterator = seq.listIterator(seq.size());
while (nestedIterator.hasPrevious() && lastBox == null) {
@@ -137,45 +195,4 @@ public class FootnoteLayoutManager extends AbstractLayoutManager
//throw new IllegalStateException("No anchor box was found for a footnote.");
}
}

/** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */
public List addALetterSpaceTo(List oldList) {
log.warn("null implementation of addALetterSpaceTo() called!");
return oldList;
}

/**
* Remove the word space represented by the given elements
*
* @param oldList the elements representing the word space
*/
public void removeWordSpace(List oldList) {
// do nothing
log.warn(this.getClass().getName() + " should not receive a call to removeWordSpace(list)");
}

/** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */
public void getWordChars(StringBuffer sbChars, Position pos) {
log.warn("null implementation of getWordChars() called!");
}

/** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */
public void hyphenate(Position pos, HyphContext hc) {
log.warn("null implementation of hyphenate called!");
}

/** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */
public boolean applyChanges(List oldList) {
log.warn("null implementation of applyChanges() called!");
return false;
}

/**
* @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int)
*/
public LinkedList getChangedKnuthElements(List oldList,
int alignment) {
log.warn("null implementation of getChangeKnuthElement() called!");
return null;
}
}

+ 3
- 0
status.xml Zobrazit soubor

@@ -28,6 +28,9 @@

<changes>
<release version="FOP Trunk">
<action context="Code" dev="LF" type="fix">
Fixed a problem with disappearing footnotes inside hyphenated inlines (and footnotes with hyphenated inline child).
</action>
<action context="Code" dev="JM" type="add" fixes-bug="42067" due-to="Paul Vinkenoog">
Add support for exact positioning of internal PDF links.
</action>

+ 0
- 6
test/layoutengine/disabled-testcases.xml Zobrazit soubor

@@ -104,12 +104,6 @@
<description>Space resolution does not work between footnote
regions.</description>
</testcase>
<testcase>
<name>Footnotes swallowed in hyphenated fo:inlines</name>
<file>footnote_in_inline.xml</file>
<description>getChangedKnuthElements probably loses the footnote
layout manager somewhere along the way.</description>
</testcase>
<testcase>
<name>Footnotes swallowed in lists</name>
<file>footnote_in_list.xml</file>

+ 2
- 1
test/layoutengine/hyphenation-testcases/footnote_in_inline.xml Zobrazit soubor

@@ -33,6 +33,7 @@
<fo:flow flow-name="xsl-region-body" language="en">
<fo:block>This is a block with a <fo:inline font-style="italic">footnote<fo:footnote><fo:inline font-size="50%" vertical-align="top">1</fo:inline><fo:footnote-body><fo:block><fo:inline font-size="50%" vertical-align="top">1</fo:inline>I'm a footnote!</fo:block></fo:footnote-body></fo:footnote></fo:inline> in it.</fo:block>
<fo:block hyphenate="true">This is a hyphenated block with a <fo:inline font-style="italic">footnote<fo:footnote><fo:inline font-size="50%" vertical-align="top">2</fo:inline><fo:footnote-body><fo:block><fo:inline font-size="50%" vertical-align="top">2</fo:inline>I'm a footnote!</fo:block></fo:footnote-body></fo:footnote></fo:inline> in it.</fo:block>
<fo:block hyphenate="true">This is a hyphenated block with a footnote<fo:footnote><fo:inline font-size="50%" vertical-align="top">hyphenation</fo:inline><fo:footnote-body><fo:block><fo:inline font-size="50%" vertical-align="top">hyphenation</fo:inline>I'm yet another footnote!</fo:block></fo:footnote-body></fo:footnote> in it.</fo:block>
<fo:block>This is another block without a footnote.</fo:block>
</fo:flow>
</fo:page-sequence>
@@ -42,6 +43,6 @@
<eval expected="1" xpath="count(//pageViewport)"/>
<!-- the footnotes -->
<eval expected="2" xpath="count(//pageViewport[1]/page/regionViewport/regionBody/footnote/block)"/>
<eval expected="3" xpath="count(//pageViewport[1]/page/regionViewport/regionBody/footnote/block)"/>
</checks>
</testcase>

Načítá se…
Zrušit
Uložit