Przeglądaj źródła

FOP-3164: basic-link not navigating to corresponding footnote by João André Gonçalves

pull/76/merge
Simon Steiner 4 miesięcy temu
rodzic
commit
bfc5d5277a

+ 10
- 0
fop-core/src/main/java/org/apache/fop/area/Area.java Wyświetl plik

*/ */
private List<ChangeBar> changeBarList; private List<ChangeBar> changeBarList;


private boolean fromFootnote;

/** /**
* Returns the active change bar list. * Returns the active change bar list.
* *
ipd = effectiveIPD; ipd = effectiveIPD;
} }
} }

public boolean isFromFootnote() {
return fromFootnote;
}

public void setFromFootnote(boolean fromFootnote) {
this.fromFootnote = fromFootnote;
}
} }

+ 19
- 2
fop-core/src/main/java/org/apache/fop/area/inline/InlineParent.java Wyświetl plik

} }
updateLevel(childArea.getBidiLevel()); updateLevel(childArea.getBidiLevel());
int childOffset = childArea.getVirtualOffset(); int childOffset = childArea.getVirtualOffset();
minChildOffset = Math.min(minChildOffset, childOffset);
maxAfterEdge = Math.max(maxAfterEdge, childOffset + childArea.getVirtualBPD());

// do not offset if the childArea comes from a footnote
// or if the parent itself comes from a footnote
if (!(childArea.isFromFootnote() || isFromFootnote())) {
minChildOffset = Math.min(minChildOffset, childOffset);
maxAfterEdge = Math.max(maxAfterEdge, childOffset + childArea.getVirtualBPD());
} else {
minChildOffset = Math.min(minChildOffset, childArea.getBlockProgressionOffset());
maxAfterEdge = minChildOffset + childArea.getVirtualBPD();
}
} }


@Override @Override
} }
} }


@Override
public void setFromFootnote(boolean fromFootnote) {
super.setFromFootnote(fromFootnote);


// set all the children to avoid offsetting any of them
// otherwise we would offset the parent by offsetting the child
for (InlineArea area : inlines) {
area.setFromFootnote(fromFootnote);
}
}
} }

+ 10
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java Wyświetl plik

*/ */
private static final Log LOG = LogFactory.getLog(AbstractBaseLayoutManager.class); private static final Log LOG = LogFactory.getLog(AbstractBaseLayoutManager.class);


private boolean fromFootnote;

/** /**
* Abstract base layout manager. * Abstract base layout manager.
*/ */
public void recreateChildrenLMs() { public void recreateChildrenLMs() {


} }

public boolean isFromFootnote() {
return fromFootnote || (getParent() != null && getParent().isFromFootnote());
}

public void setFromFootnote(boolean fromFootnote) {
this.fromFootnote = fromFootnote;
}
} }

+ 2
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java Wyświetl plik

lc.setFlags(LayoutContext.LAST_AREA, lc.setFlags(LayoutContext.LAST_AREA,
(layoutContext.isLastArea() && childLM == lastLM)); (layoutContext.isLastArea() && childLM == lastLM));
// Add the line areas to Area // Add the line areas to Area
childLM.setFromFootnote(true);
childLM.addAreas(childPosIter, lc); childLM.addAreas(childPosIter, lc);
} }
} }
@Override @Override
public void addChildArea(Area childArea) { public void addChildArea(Area childArea) {
childArea.setAreaClass(Area.CLASS_FOOTNOTE); childArea.setAreaClass(Area.CLASS_FOOTNOTE);
childArea.setFromFootnote(true);
parentLayoutManager.addChildArea(childArea); parentLayoutManager.addChildArea(childArea);
} }



+ 4
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManager.java Wyświetl plik

*/ */
List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack, List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
Position positionAtIPDChange, LayoutManager restartAtLM); Position positionAtIPDChange, LayoutManager restartAtLM);

boolean isFromFootnote();

void setFromFootnote(boolean fromFootnote);
} }

+ 1
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java Wyświetl plik

PositionIterator childPosIter = new PositionIterator(positionList.listIterator()); PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
LayoutManager childLM; LayoutManager childLM;
while ((childLM = childPosIter.getNextChildLM()) != null) { while ((childLM = childPosIter.getNextChildLM()) != null) {
childLM.setFromFootnote(true);
childLM.addAreas(childPosIter, childContext); childLM.addAreas(childPosIter, childContext);
childContext.setLeadingSpace(childContext.getTrailingSpace()); childContext.setLeadingSpace(childContext.getTrailingSpace());
childContext.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); childContext.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);

+ 1
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java Wyświetl plik

// Not sure if lastPos can legally be null or if that masks a different problem. // Not sure if lastPos can legally be null or if that masks a different problem.
// But it seems to fix bug 38053. // But it seems to fix bug 38053.
setTraits(areaCreated, lastPos == null || !isLast(lastPos)); setTraits(areaCreated, lastPos == null || !isLast(lastPos));
getCurrentArea().setFromFootnote(isFromFootnote());
parentLayoutManager.addChildArea(getCurrentArea()); parentLayoutManager.addChildArea(getCurrentArea());


registerMarkers( registerMarkers(

+ 2
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java Wyświetl plik

if (level >= 0) { if (level >= 0) {
ls.setBidiLevel(level); ls.setBidiLevel(level);
} }
ls.setFromFootnote(isFromFootnote());

parentArea.addChildArea(ls); parentArea.addChildArea(ls);
} }
} }

+ 1
- 0
fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java Wyświetl plik

textArea.setTextLetterSpaceAdjust(letterSpaceDim); textArea.setTextLetterSpaceAdjust(letterSpaceDim);
textArea.setTextWordSpaceAdjust(wordSpaceDim - spaceCharIPD textArea.setTextWordSpaceAdjust(wordSpaceDim - spaceCharIPD
- 2 * textArea.getTextLetterSpaceAdjust()); - 2 * textArea.getTextLetterSpaceAdjust());
textArea.setFromFootnote(isFromFootnote());
if (context.getIPDAdjust() != 0) { if (context.getIPDAdjust() != 0) {
// add information about space width // add information about space width
textArea.setSpaceDifference(wordSpaceIPD.getOpt() - spaceCharIPD textArea.setSpaceDifference(wordSpaceIPD.getOpt() - spaceCharIPD

+ 116
- 0
fop-core/src/test/java/org/apache/fop/area/inline/InlineParentTestCase.java Wyświetl plik

/*
* 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$ */

package org.apache.fop.area.inline;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class InlineParentTestCase {

private static final int BLOCK_PROG_OFFSET = -12;

private static final int BPD = 25;

@Test
public void testAddChildAreaMixedFromFootnote() {
InlineParent parent = new InlineParent();
InlineParent firstChild = createChildInlineParent(BLOCK_PROG_OFFSET, BPD, false);
InlineParent secondChild = createChildInlineParent(3 * BLOCK_PROG_OFFSET, 3 * BPD, false);
InlineParent thirdChild = createChildInlineParent(2 * BLOCK_PROG_OFFSET, 2 * BPD, true);
InlineParent forthChild = createChildInlineParent(0, 0, true);

assertEquals("Default Values must be zero", 0, parent.minChildOffset);
assertEquals("Default Values must be zero", 0, parent.getVirtualBPD());

assertAddChildArea(parent, firstChild, -12, 0);
assertAddChildArea(parent, secondChild, -36, 0);
assertAddChildArea(parent, thirdChild, -36, -36);
assertAddChildArea(parent, forthChild, -36, -36);
}

@Test
public void testAddChildAreaNotFromFootnote() {
InlineParent parent = new InlineParent();
InlineParent firstChild = createChildInlineParent(BLOCK_PROG_OFFSET, BPD, false);
InlineParent secondChild = createChildInlineParent(3 * BLOCK_PROG_OFFSET, 3 * BPD, false);
InlineParent thirdChild = createChildInlineParent(2 * BLOCK_PROG_OFFSET, 2 * BPD, false);
InlineParent forthChild = createChildInlineParent(0, 0, false);

assertEquals("Default Values must be zero", 0, parent.minChildOffset);
assertEquals("Default Values must be zero", 0, parent.getVirtualBPD());

assertAddChildArea(parent, firstChild, -12, 0);
assertAddChildArea(parent, secondChild, -36, 0);
assertAddChildArea(parent, thirdChild, -36, 0);
assertAddChildArea(parent, forthChild, -36, 0);
}

@Test
public void testAddChildAreaFromFootnote() {
InlineParent parent = new InlineParent();
InlineParent firstChild = createChildInlineParent(BLOCK_PROG_OFFSET, BPD, true);
InlineParent secondChild = createChildInlineParent(3 * BLOCK_PROG_OFFSET, 3 * BPD, true);
InlineParent thirdChild = createChildInlineParent(2 * BLOCK_PROG_OFFSET, 2 * BPD, true);
InlineParent forthChild = createChildInlineParent(0, 0, true);

assertEquals("Default Values must be zero", 0, parent.minChildOffset);
assertEquals("Default Values must be zero", 0, parent.getVirtualBPD());

assertAddChildArea(parent, firstChild, -12, -12);
assertAddChildArea(parent, secondChild, -36, -36);
assertAddChildArea(parent, thirdChild, -36, -36);
assertAddChildArea(parent, forthChild, -36, -36);
}

private void assertAddChildArea(InlineParent parent, InlineParent child,
int minChildOffset, int maxAfterEdge) {
parent.addChildArea(child);

// the virtualBPD is the subtraction of the maxAfterEdge with the minChildOffset
// by adding the minChildOffset to the virtualBPD we get the maxAfterEdge alone
int parentMaxAfterEdge = parent.getVirtualBPD() + parent.minChildOffset;

if (!child.isFromFootnote()) {
assertEquals("Must be set to the min of the current minChildOffset and the "
+ "sum of the child's virtualOffset with the current value of the minChildOffset",
minChildOffset, parent.minChildOffset);
assertEquals("Must be set to the max of the current maxAfterEdge and the "
+ "result of the sum of the child's virtualOffset with child's the virtualBPD",
maxAfterEdge, parentMaxAfterEdge);
} else {
assertEquals("Must be set to the min of the current minChildOffset and the "
+ "sum of the child's blockProgressionOffset with the current value "
+ "of the minChildOffset",
minChildOffset, parent.minChildOffset);
assertEquals("Must be the result of the sum of the maxAfterEdge "
+ "with the child's virtualBPD", maxAfterEdge, parentMaxAfterEdge);
}
}

private InlineParent createChildInlineParent(int bpo, int bpd, boolean footnote) {
InlineParent child = new InlineParent();
child.setBlockProgressionOffset(bpo);
child.setBPD(bpd);
child.setFromFootnote(footnote);

return child;
}
}

+ 90
- 0
fop/test/layoutengine/standard-testcases/footnote_basic_link.xml Wyświetl plik

<?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.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="3in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal" white-space-collapse="true">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<!-- Mid-Link Footnote -->
<fo:block>
<fo:basic-link external-destination="https://www.google.com/">
<fo:inline>This is a link with a footnote</fo:inline>
<fo:footnote>
<fo:inline>
<fo:basic-link id="fn-ref-2" internal-destination="fn-2" color="blue">
<fo:inline baseline-shift="super" font-size="80%">1</fo:inline>
</fo:basic-link>
</fo:inline>
<fo:footnote-body>
<fo:block color="black" text-decoration="none">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="proportional-column-width(5)"/>
<fo:table-column column-width="proportional-column-width(95)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>
<fo:basic-link id="fn-2" internal-destination="fn-ref-2" color="blue">1</fo:basic-link>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Note text</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:footnote-body>
</fo:footnote>
<fo:inline> inside</fo:inline>
</fo:basic-link>
</fo:block>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<!-- block with footnote -->
<eval expected="This is a link with a footnote 1 inside" xpath="//inlineparent[1]"/>
<eval expected=" 1" xpath="//inlineparent[2]"/>
<!-- the footnote -->
<eval expected="4552" xpath="//inlineparent[1]/@offset"/>
<eval expected="11100" xpath="//inlineparent[1]/@bpd"/>
<eval expected="11100" xpath="//inlineparent[1]/@bpda"/>

<eval expected="0" xpath="//inlineparent[2]/@offset"/>
<eval expected="11100" xpath="//inlineparent[2]/@bpd"/>
<eval expected="11100" xpath="//inlineparent[2]/@bpda"/>

<eval expected="15652" xpath="//lineArea/@bpd"/>
<eval expected="18952" xpath="//lineArea/@bpda"/>
</checks>
</testcase>

Ładowanie…
Anuluj
Zapisz