git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1834850 13f79535-47bb-0310-9956-ffa450edef68pull/19/head
this.documentMetadata = metadata.getMetadata(); | this.documentMetadata = metadata.getMetadata(); | ||||
} | } | ||||
private GoToXYAction getGoToActionForID(String targetID, int pageIndex) { | |||||
private GoToXYAction getGoToActionForID(String targetID, final int pageIndex) { | |||||
// Already a GoToXY present for this target? If not, create. | // Already a GoToXY present for this target? If not, create. | ||||
GoToXYAction action = (GoToXYAction)actionSet.get(targetID); | GoToXYAction action = (GoToXYAction)actionSet.get(targetID); | ||||
//GoToXYAction action = (GoToXYAction)idGoTos.get(targetID); | //GoToXYAction action = (GoToXYAction)idGoTos.get(targetID); | ||||
Point position = (Point)idPositions.get(targetID); | Point position = (Point)idPositions.get(targetID); | ||||
// can the GoTo already be fully filled in? | // can the GoTo already be fully filled in? | ||||
if (pageIndex >= 0 && position != null) { | if (pageIndex >= 0 && position != null) { | ||||
action = new GoToXYAction(targetID, pageIndex, position); | |||||
action = new GoToXYAction(targetID, pageIndex, position, new GoToXYAction.PageIndexRelative() { | |||||
public int getPageIndexRelative() { | |||||
return pageIndex - documentHandler.getContext().getPageIndex(); | |||||
} | |||||
}); | |||||
} else { | } else { | ||||
// Not complete yet, can't use getPDFGoTo: | // Not complete yet, can't use getPDFGoTo: | ||||
action = new GoToXYAction(targetID, pageIndex, null); | |||||
action = new GoToXYAction(targetID, pageIndex, null, null); | |||||
unfinishedGoTos.add(action); | unfinishedGoTos.add(action); | ||||
} | } | ||||
action = (GoToXYAction)actionSet.put(action); | action = (GoToXYAction)actionSet.put(action); |
} else { | } else { | ||||
String id = attributes.getValue("id"); | String id = attributes.getValue("id"); | ||||
int pageIndex = XMLUtil.getAttributeAsInt(attributes, "page-index"); | int pageIndex = XMLUtil.getAttributeAsInt(attributes, "page-index"); | ||||
final int pageIndexRelative = XMLUtil.getAttributeAsInt(attributes, "page-index-relative", 0); | |||||
final Point location; | final Point location; | ||||
if (pageIndex < 0) { | if (pageIndex < 0) { | ||||
location = null; | location = null; | ||||
} else { | } else { | ||||
if (hasNavigation() && !inBookmark()) { | |||||
if (hasNavigation() && !inBookmark() && pageIndexRelative >= 0) { | |||||
int currentPageIndex = navHandler.getPageIndex(); | int currentPageIndex = navHandler.getPageIndex(); | ||||
if (currentPageIndex >= 0) { | if (currentPageIndex >= 0) { | ||||
pageIndex = currentPageIndex; | pageIndex = currentPageIndex; | ||||
.getAttributeAsInt(attributes, "y"); | .getAttributeAsInt(attributes, "y"); | ||||
location = new Point(x, y); | location = new Point(x, y); | ||||
} | } | ||||
action = new GoToXYAction(id, pageIndex, location); | |||||
action = new GoToXYAction(id, pageIndex, location, new GoToXYAction.PageIndexRelative() { | |||||
public int getPageIndexRelative() { | |||||
return pageIndexRelative; | |||||
} | |||||
}); | |||||
} | } | ||||
if (structureTreeElement != null) { | if (structureTreeElement != null) { | ||||
action.setStructureTreeElement(structureTreeElement); | action.setStructureTreeElement(structureTreeElement); |
public class GoToXYAction extends AbstractAction implements DocumentNavigationExtensionConstants { | public class GoToXYAction extends AbstractAction implements DocumentNavigationExtensionConstants { | ||||
private int pageIndex = -1; | private int pageIndex = -1; | ||||
private PageIndexRelative pageIndexRelative; | |||||
private Point targetLocation; | private Point targetLocation; | ||||
/** | /** | ||||
* @param id the identifier for this action | * @param id the identifier for this action | ||||
*/ | */ | ||||
public GoToXYAction(String id) { | public GoToXYAction(String id) { | ||||
this(id, -1, null); | |||||
this(id, -1, null, null); | |||||
} | } | ||||
/** | /** | ||||
* @param targetLocation the absolute location on the page (coordinates in millipoints), | * @param targetLocation the absolute location on the page (coordinates in millipoints), | ||||
* or null, if the position isn't known, yet | * or null, if the position isn't known, yet | ||||
*/ | */ | ||||
public GoToXYAction(String id, int pageIndex, Point targetLocation) { | |||||
public GoToXYAction(String id, int pageIndex, Point targetLocation, PageIndexRelative pageIndexRelative) { | |||||
setID(id); | setID(id); | ||||
if (pageIndex < 0 && targetLocation != null) { | if (pageIndex < 0 && targetLocation != null) { | ||||
throw new IllegalArgumentException( | throw new IllegalArgumentException( | ||||
} | } | ||||
setPageIndex(pageIndex); | setPageIndex(pageIndex); | ||||
setTargetLocation(targetLocation); | setTargetLocation(targetLocation); | ||||
this.pageIndexRelative = pageIndexRelative; | |||||
} | |||||
public interface PageIndexRelative { | |||||
int getPageIndexRelative(); | |||||
} | } | ||||
/** | /** | ||||
atts.addAttribute("", "id", "id", XMLUtil.CDATA, getID()); | atts.addAttribute("", "id", "id", XMLUtil.CDATA, getID()); | ||||
atts.addAttribute("", "page-index", "page-index", | atts.addAttribute("", "page-index", "page-index", | ||||
XMLUtil.CDATA, Integer.toString(pageIndex)); | XMLUtil.CDATA, Integer.toString(pageIndex)); | ||||
if (pageIndexRelative != null) { | |||||
int pageIndexRelativeInt = pageIndexRelative.getPageIndexRelative(); | |||||
if (pageIndexRelativeInt < 0) { | |||||
atts.addAttribute("", "page-index-relative", "page-index-relative", | |||||
XMLUtil.CDATA, Integer.toString(pageIndexRelativeInt)); | |||||
} | |||||
} | |||||
atts.addAttribute("", "x", "x", XMLUtil.CDATA, | atts.addAttribute("", "x", "x", XMLUtil.CDATA, | ||||
Integer.toString(reportedTargetLocation.x)); | Integer.toString(reportedTargetLocation.x)); | ||||
atts.addAttribute("", "y", "y", XMLUtil.CDATA, | atts.addAttribute("", "y", "y", XMLUtil.CDATA, |
throw new IOException(name + " not found " + firstObj); | throw new IOException(name + " not found " + firstObj); | ||||
} | } | ||||
private String getObj(Collection<StringBuilder> objs, String x) { | |||||
public static String getObj(Collection<StringBuilder> objs, String x) { | |||||
for (StringBuilder s : objs) { | for (StringBuilder s : objs) { | ||||
if (s.toString().contains(x)) { | if (s.toString().contains(x)) { | ||||
return s.toString(); | return s.toString(); |
package org.apache.fop.render.extensions; | package org.apache.fop.render.extensions; | ||||
import java.awt.Dimension; | import java.awt.Dimension; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.Collection; | |||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.List; | import java.util.List; | ||||
import org.apache.fop.apps.FOUserAgent; | import org.apache.fop.apps.FOUserAgent; | ||||
import org.apache.fop.apps.FopFactory; | import org.apache.fop.apps.FopFactory; | ||||
import org.apache.fop.fonts.FontInfo; | import org.apache.fop.fonts.FontInfo; | ||||
import org.apache.fop.pdf.PDFLinearizationTestCase; | |||||
import org.apache.fop.pdf.PDFVTTestCase; | |||||
import org.apache.fop.render.intermediate.IFContext; | import org.apache.fop.render.intermediate.IFContext; | ||||
import org.apache.fop.render.intermediate.IFException; | import org.apache.fop.render.intermediate.IFException; | ||||
import org.apache.fop.render.intermediate.extensions.AbstractAction; | import org.apache.fop.render.intermediate.extensions.AbstractAction; | ||||
Assert.assertEquals(goToXYActions.get(0).getPageIndex(), currentPage); | Assert.assertEquals(goToXYActions.get(0).getPageIndex(), currentPage); | ||||
} | } | ||||
@Test | |||||
public void testGotoXYPrevousPage() throws SAXException, IFException, IOException { | |||||
FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); | |||||
PDFDocumentHandler documentHandler = new PDFDocumentHandler(new IFContext(ua)); | |||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |||||
documentHandler.setResult(new StreamResult(bos)); | |||||
documentHandler.setFontInfo(new FontInfo()); | |||||
documentHandler.startDocument(); | |||||
documentHandler.startPage(0, "", "", new Dimension()); | |||||
documentHandler.endPage(); | |||||
documentHandler.startPage(1, "", "", new Dimension()); | |||||
final List<GoToXYAction> goToXYActions = new ArrayList<GoToXYAction>(); | |||||
PDFDocumentNavigationHandler pdfDocumentNavigationHandler = new PDFDocumentNavigationHandler(documentHandler) { | |||||
public void addResolvedAction(AbstractAction action) throws IFException { | |||||
super.addResolvedAction(action); | |||||
goToXYActions.add((GoToXYAction) action); | |||||
} | |||||
}; | |||||
DocumentNavigationHandler navigationHandler = new DocumentNavigationHandler(pdfDocumentNavigationHandler, | |||||
new HashMap<String, StructureTreeElement>()); | |||||
QName xy = DocumentNavigationExtensionConstants.GOTO_XY; | |||||
Attributes attributes = mock(Attributes.class); | |||||
when(attributes.getValue("page-index")).thenReturn("0"); | |||||
when(attributes.getValue("page-index-relative")).thenReturn("-1"); | |||||
when(attributes.getValue("x")).thenReturn("0"); | |||||
when(attributes.getValue("y")).thenReturn("0"); | |||||
navigationHandler.startElement(xy.getNamespaceURI(), xy.getLocalName(), null, attributes); | |||||
navigationHandler.endElement(xy.getNamespaceURI(), xy.getLocalName(), null); | |||||
documentHandler.endPage(); | |||||
documentHandler.endDocument(); | |||||
Assert.assertEquals(goToXYActions.get(0).getPageIndex(), 0); | |||||
Collection<StringBuilder> objs = PDFLinearizationTestCase.readObjs( | |||||
new ByteArrayInputStream(bos.toByteArray())).values(); | |||||
String pages = PDFVTTestCase.getObj(objs, "/Type /Pages"); | |||||
String action = PDFVTTestCase.getObj(objs, "/Type /Action"); | |||||
String pageRef = action.split("\\[")[1].split(" /XYZ")[0]; | |||||
Assert.assertTrue(pageRef.endsWith(" 0 R")); | |||||
Assert.assertTrue(pages.contains("/Kids [" + pageRef)); | |||||
} | |||||
@Test | @Test | ||||
public void testGotoXYUniqueLinks() throws IFException, SAXException { | public void testGotoXYUniqueLinks() throws IFException, SAXException { | ||||
FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); | FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); |
<xs:complexType> | <xs:complexType> | ||||
<xs:attributeGroup ref="nav:refDef"/> | <xs:attributeGroup ref="nav:refDef"/> | ||||
<xs:attribute name="page-index" type="xs:int"/> | <xs:attribute name="page-index" type="xs:int"/> | ||||
<xs:attribute name="page-index-relative" type="xs:int" use="optional"/> | |||||
<xs:attributeGroup ref="nav:posAtts"/> | <xs:attributeGroup ref="nav:posAtts"/> | ||||
</xs:complexType> | </xs:complexType> | ||||
</xs:element> | </xs:element> |