diff options
author | Simon Steiner <ssteiner@apache.org> | 2022-01-19 10:43:17 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2022-01-19 10:43:17 +0000 |
commit | 63c0ce941e58f3673a586527e1669639494ecf6e (patch) | |
tree | 3859f8aaf1fa792f8130d783131b24e1c1975255 /fop-core/src | |
parent | bbd7343ba13043f8f78e175363037f052d648395 (diff) | |
download | xmlgraphics-fop-63c0ce941e58f3673a586527e1669639494ecf6e.tar.gz xmlgraphics-fop-63c0ce941e58f3673a586527e1669639494ecf6e.zip |
FOP-3048: Resolve links across IF files
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1897194 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'fop-core/src')
6 files changed, 88 insertions, 25 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/area/RenderPagesModel.java b/fop-core/src/main/java/org/apache/fop/area/RenderPagesModel.java index b94a32b4b..91d8d4e22 100644 --- a/fop-core/src/main/java/org/apache/fop/area/RenderPagesModel.java +++ b/fop-core/src/main/java/org/apache/fop/area/RenderPagesModel.java @@ -191,15 +191,6 @@ public class RenderPagesModel extends AreaTreeModel { protected void renderPage(PageViewport pageViewport) { try { renderer.renderPage(pageViewport); - if (!pageViewport.isResolved()) { - String[] idrefs = pageViewport.getIDRefs(); - for (String idref : idrefs) { - AreaEventProducer eventProducer = AreaEventProducer.Provider.get( - renderer.getUserAgent().getEventBroadcaster()); - eventProducer.unresolvedIDReferenceOnPage(this, - pageViewport.getPageNumberString(), idref); - } - } } catch (Exception e) { AreaEventProducer eventProducer = AreaEventProducer.Provider.get( renderer.getUserAgent().getEventBroadcaster()); diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java index 3745da00e..a75e61cf3 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java @@ -58,6 +58,7 @@ import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.extensions.InternalElementMapping; import org.apache.fop.render.intermediate.extensions.DocumentNavigationExtensionConstants; import org.apache.fop.render.intermediate.extensions.DocumentNavigationHandler; +import org.apache.fop.render.intermediate.extensions.GoToXYAction; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.ColorUtil; @@ -164,6 +165,7 @@ public class IFParser implements IFConstants { private Map<String, StructureTreeElement> structureTreeElements = new HashMap<String, StructureTreeElement>(); + private Map<String, GoToXYAction> unresolvedIds = new HashMap<>(); private class StructureTreeHandler extends DefaultHandler { @@ -308,12 +310,24 @@ public class IFParser implements IFConstants { .noStructureTreeInXML(this); } handled = startIFElement(localName, attributes); + + if (EL_ID.equals(localName) && documentHandler.getDocumentNavigationHandler() != null) { + if (this.navParser == null) { + this.navParser = new DocumentNavigationHandler( + documentHandler.getDocumentNavigationHandler(), + structureTreeElements, unresolvedIds); + } + delegate = this.navParser; + delegateDepth++; + delegate.startDocument(); + delegate.startElement(uri, localName, qName, attributes); + } } } else if (DocumentNavigationExtensionConstants.NAMESPACE.equals(uri)) { if (this.navParser == null) { this.navParser = new DocumentNavigationHandler( this.documentHandler.getDocumentNavigationHandler(), - structureTreeElements); + structureTreeElements, unresolvedIds); } delegate = this.navParser; delegateDepth++; @@ -410,6 +424,9 @@ public class IFParser implements IFConstants { ElementHandler elementHandler = elementHandlers.get(localName); if (elementHandler != null) { try { + if (elementHandler instanceof DocumentHandler) { + addUnresolvedIds(); + } elementHandler.endElement(); } catch (IFException ife) { handleIFException(ife); @@ -425,6 +442,14 @@ public class IFParser implements IFConstants { } } + private void addUnresolvedIds() throws IFException { + for (GoToXYAction action : unresolvedIds.values()) { + if (action != null) { + documentHandler.getDocumentNavigationHandler().addResolvedAction(action); + } + } + } + // ============== Element handlers for the intermediate format ============= private interface ElementHandler { diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java index 5a401b1a7..da010d21a 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -68,6 +68,7 @@ import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.AbstractTextArea; +import org.apache.fop.area.inline.BasicLinkArea; import org.apache.fop.area.inline.ForeignObject; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.InlineArea; @@ -95,7 +96,6 @@ import org.apache.fop.render.intermediate.extensions.GoToXYAction; import org.apache.fop.render.intermediate.extensions.Link; import org.apache.fop.render.intermediate.extensions.NamedDestination; import org.apache.fop.render.intermediate.extensions.URIAction; -import org.apache.fop.render.pdf.PDFEventProducer; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; @@ -427,9 +427,6 @@ public class IFRenderer extends AbstractPathOrientedRenderer { GoToXYAction action = (GoToXYAction)unfinishedGoTos.get(0); noteGoToPosition(action, defaultPos); } - PDFEventProducer eventProducer = PDFEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.nonFullyResolvedLinkTargets(this, count); // dysfunctional if pageref is null } } @@ -981,6 +978,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer { action.setStructureTreeElement(structElem); Link link = new Link(action, ipRect); this.deferredLinks.add(link); + } else if (ip instanceof BasicLinkArea) { + BasicLinkArea linkArea = (BasicLinkArea) ip; + String id = linkArea.getResolver().getIDRefs()[0]; + action = getGoToActionForID(id, -1); + Link link = new Link(action, ipRect); + this.deferredLinks.add(link); } } diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java index 69743708d..f654ef37e 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java @@ -38,6 +38,8 @@ import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.PageIndexContext; import org.apache.fop.util.XMLUtil; +import static org.apache.fop.render.intermediate.IFConstants.EL_ID; + /** * ContentHandler that handles the IF document navigation namespace. */ @@ -46,9 +48,11 @@ public class DocumentNavigationHandler extends DefaultHandler /** Logger instance */ protected static final Log log = LogFactory.getLog(DocumentNavigationHandler.class); + private static final String NAME = "name"; private StringBuffer content = new StringBuffer(); private Stack objectStack = new Stack(); + private Map<String, GoToXYAction> unresolvedIds; private IFDocumentNavigationHandler navHandler; @@ -62,16 +66,27 @@ public class DocumentNavigationHandler extends DefaultHandler * @param structureTreeElements the elements representing the structure of the document */ public DocumentNavigationHandler(IFDocumentNavigationHandler navHandler, - Map<String, StructureTreeElement> structureTreeElements) { + Map<String, StructureTreeElement> structureTreeElements, Map<String, GoToXYAction> unresolvedIds) { this.navHandler = navHandler; assert structureTreeElements != null; this.structureTreeElements = structureTreeElements; + this.unresolvedIds = unresolvedIds; } /** {@inheritDoc} */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { boolean handled = false; + if (EL_ID.equals(localName)) { + String idref = attributes.getValue(NAME); + if (unresolvedIds.containsKey(idref)) { + GoToXYAction action = new GoToXYAction(idref); + action.setPageIndex(navHandler.getPageIndex()); + action.setTargetLocation(new Point(0, 0)); + unresolvedIds.put(idref, action); + } + handled = true; + } if (NAMESPACE.equals(uri)) { if (BOOKMARK_TREE.getLocalName().equals(localName)) { if (!objectStack.isEmpty()) { @@ -124,6 +139,7 @@ public class DocumentNavigationHandler extends DefaultHandler final Point location; if (pageIndex < 0) { location = null; + unresolvedIds.put(id, null); } else { if (hasNavigation() && !inBookmark() && pageIndexRelative >= 0) { int currentPageIndex = navHandler.getPageIndex(); @@ -136,6 +152,7 @@ public class DocumentNavigationHandler extends DefaultHandler final int y = XMLUtil .getAttributeAsInt(attributes, "y"); location = new Point(x, y); + unresolvedIds.remove(id); } action = new GoToXYAction(id, pageIndex, location, new PageIndexRelative(pageIndex, pageIndexRelative)); diff --git a/fop-core/src/test/java/org/apache/fop/events/EventProcessingTestCase.java b/fop-core/src/test/java/org/apache/fop/events/EventProcessingTestCase.java index 66ec43193..5e96883ec 100644 --- a/fop-core/src/test/java/org/apache/fop/events/EventProcessingTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/events/EventProcessingTestCase.java @@ -106,12 +106,6 @@ public class EventProcessingTestCase { } @Test - public void testArea() throws Exception { - doTest("area.fo", - AreaEventProducer.class.getName() + ".unresolvedIDReferenceOnPage"); - } - - @Test public void testBookmarks() throws Exception { doTest("bookmarks.fo", AreaEventProducer.class.getName() + ".unresolvedIDReference"); diff --git a/fop-core/src/test/java/org/apache/fop/render/extensions/DocumentNavigationHandlerTestCase.java b/fop-core/src/test/java/org/apache/fop/render/extensions/DocumentNavigationHandlerTestCase.java index 327f31aa5..1b8efd112 100644 --- a/fop-core/src/test/java/org/apache/fop/render/extensions/DocumentNavigationHandlerTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/render/extensions/DocumentNavigationHandlerTestCase.java @@ -23,6 +23,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -30,7 +31,13 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; import org.junit.Assert; import org.junit.Test; @@ -45,11 +52,15 @@ import org.apache.xmlgraphics.util.QName; import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; 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.IFDocumentHandler; import org.apache.fop.render.intermediate.IFException; +import org.apache.fop.render.intermediate.IFParser; +import org.apache.fop.render.intermediate.IFUtil; import org.apache.fop.render.intermediate.extensions.AbstractAction; import org.apache.fop.render.intermediate.extensions.Bookmark; import org.apache.fop.render.intermediate.extensions.BookmarkTree; @@ -81,7 +92,7 @@ public class DocumentNavigationHandlerTestCase { } }; DocumentNavigationHandler navigationHandler = new DocumentNavigationHandler(pdfDocumentNavigationHandler, - new HashMap<String, StructureTreeElement>()); + new HashMap<String, StructureTreeElement>(), new HashMap<String, GoToXYAction>()); QName xy = DocumentNavigationExtensionConstants.GOTO_XY; Attributes attributes = mock(Attributes.class); when(attributes.getValue("page-index")).thenReturn("0"); @@ -96,6 +107,28 @@ public class DocumentNavigationHandlerTestCase { } @Test + public void testGotoXYMergedIF() throws Exception { + InputStream ifXml = getClass().getResourceAsStream("link.if.xml"); + ByteArrayOutputStream pdf = iFToPDF(ifXml); + Assert.assertTrue(pdf.toString().contains("/S /GoTo")); + } + + private ByteArrayOutputStream iFToPDF(InputStream is) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + FOUserAgent userAgent = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + Source src = new StreamSource(is); + IFDocumentHandler documentHandler + = userAgent.getRendererFactory().createDocumentHandler(userAgent, MimeConstants.MIME_PDF); + documentHandler.setResult(new StreamResult(out)); + IFUtil.setupFonts(documentHandler); + IFParser parser = new IFParser(); + Result res = new SAXResult(parser.getContentHandler(documentHandler, userAgent)); + transformer.transform(src, res); + return out; + } + + @Test public void testGotoXYPrevousPage() throws SAXException, IFException, IOException { FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); PDFDocumentHandler documentHandler = new PDFDocumentHandler(new IFContext(ua)); @@ -116,7 +149,7 @@ public class DocumentNavigationHandlerTestCase { } }; DocumentNavigationHandler navigationHandler = new DocumentNavigationHandler(pdfDocumentNavigationHandler, - new HashMap<String, StructureTreeElement>()); + new HashMap<String, StructureTreeElement>(), new HashMap<String, GoToXYAction>()); QName xy = DocumentNavigationExtensionConstants.GOTO_XY; Attributes attributes = mock(Attributes.class); when(attributes.getValue("page-index")).thenReturn("0"); @@ -150,7 +183,7 @@ public class DocumentNavigationHandlerTestCase { PDFDocumentNavigationHandler pdfDocumentNavigationHandler = new PDFDocumentNavigationHandler(documentHandler); DocumentNavigationHandler navigationHandler = new DocumentNavigationHandler(pdfDocumentNavigationHandler, - new HashMap<String, StructureTreeElement>()); + new HashMap<String, StructureTreeElement>(), new HashMap<String, GoToXYAction>()); QName xy = DocumentNavigationExtensionConstants.GOTO_XY; Attributes attributes = mock(Attributes.class); @@ -199,7 +232,7 @@ public class DocumentNavigationHandlerTestCase { } }; DocumentNavigationHandler navigationHandler = new DocumentNavigationHandler(pdfDocumentNavigationHandler, - new HashMap<String, StructureTreeElement>()); + new HashMap<String, StructureTreeElement>(), new HashMap<String, GoToXYAction>()); Attributes attributes = mock(Attributes.class); when(attributes.getValue("page-index")).thenReturn("0"); when(attributes.getValue("x")).thenReturn("0"); |