View | Details | Raw Unified | Return to bug 45759
Collapse All | Expand All

(-)src/java/org/apache/fop/render/pdf/PDFRenderer.java (+20 lines)
Lines 1401-1406 Link Here
1401
        }
1401
        }
1402
    }
1402
    }
1403
1403
1404
    /**
1405
     * Render an internal link explicitly.
1406
     * For normal PDF text, this is handled by
1407
     * renderInlineParent. This is used when rendering SVG's to
1408
     * explicitly add internal links.
1409
     * @param rect Area to add link to
1410
     * @param idRef The target id to link to
1411
     */
1412
    public void renderInternalLink(Rectangle2D rect, String idRef) {
1413
        boolean annotsAllowed = pdfDoc.getProfile().isAnnotationAllowed();
1414
        boolean idRefOK = idRef != null && idRef.length() > 0;
1415
        if (idRefOK && annotsAllowed) {
1416
            PDFFactory factory = pdfDoc.getFactory();
1417
            PDFAction action = getPDFGoToForID(idRef, null);
1418
            /* using null as pvKey will delay the link resolution */
1419
            PDFLink pdfLink = factory.makeLink(rect, action);
1420
            currentPage.addAnnotation(pdfLink);
1421
        }
1422
    }
1423
1404
    private Typeface getTypeface(String fontName) {
1424
    private Typeface getTypeface(String fontName) {
1405
        Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
1425
        Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
1406
        if (tf instanceof LazyFont) {
1426
        if (tf instanceof LazyFont) {
(-)src/java/org/apache/fop/render/pdf/PDFSVGHandler.java (-2 / +54 lines)
Lines 20-26 Link Here
20
package org.apache.fop.render.pdf;
20
package org.apache.fop.render.pdf;
21
21
22
import java.awt.Color;
22
import java.awt.Color;
23
import java.awt.Shape;
23
import java.awt.geom.AffineTransform;
24
import java.awt.geom.AffineTransform;
25
import java.awt.geom.Rectangle2D;
24
import java.io.IOException;
26
import java.io.IOException;
25
import java.io.OutputStream;
27
import java.io.OutputStream;
26
import java.util.Map;
28
import java.util.Map;
Lines 51-56 Link Here
51
import org.apache.fop.render.RendererContext;
53
import org.apache.fop.render.RendererContext;
52
import org.apache.fop.render.RendererContextConstants;
54
import org.apache.fop.render.RendererContextConstants;
53
import org.apache.fop.svg.PDFAElementBridge;
55
import org.apache.fop.svg.PDFAElementBridge;
56
import org.apache.fop.svg.PDFANode;
54
import org.apache.fop.svg.PDFBridgeContext;
57
import org.apache.fop.svg.PDFBridgeContext;
55
import org.apache.fop.svg.PDFGraphics2D;
58
import org.apache.fop.svg.PDFGraphics2D;
56
import org.apache.fop.svg.SVGEventProducer;
59
import org.apache.fop.svg.SVGEventProducer;
Lines 140-146 Link Here
140
     */
143
     */
141
    protected void renderSVGDocument(RendererContext context,
144
    protected void renderSVGDocument(RendererContext context,
142
            Document doc) {
145
            Document doc) {
143
        PDFRenderer renderer = (PDFRenderer)context.getRenderer();
146
        final PDFRenderer renderer = (PDFRenderer)context.getRenderer();
144
        PDFInfo pdfInfo = getPDFInfo(context);
147
        PDFInfo pdfInfo = getPDFInfo(context);
145
        if (pdfInfo.paintAsBitmap) {
148
        if (pdfInfo.paintAsBitmap) {
146
            try {
149
            try {
Lines 182-189 Link Here
182
                (strokeText ? null : pdfInfo.fi),
185
                (strokeText ? null : pdfInfo.fi),
183
                userAgent.getFactory().getImageManager(),
186
                userAgent.getFactory().getImageManager(),
184
                userAgent.getImageSessionContext(),
187
                userAgent.getImageSessionContext(),
185
                new AffineTransform());
188
                new AffineTransform()) {
186
189
190
            /** {@inheritDoc} */
191
            protected PDFAElementBridge createPDFAElementBridge() {
192
                //return super.createPDFAElementBridge();
193
                return new LinkBackAElementBridge(renderer);
194
            }
195
196
        };
197
187
        GraphicsNode root;
198
        GraphicsNode root;
188
        try {
199
        try {
189
            root = builder.build(ctx, doc);
200
            root = builder.build(ctx, doc);
Lines 276-279 Link Here
276
    public boolean supportsRenderer(Renderer renderer) {
287
    public boolean supportsRenderer(Renderer renderer) {
277
        return (renderer instanceof PDFRenderer);
288
        return (renderer instanceof PDFRenderer);
278
    }
289
    }
290
291
    private class LinkBackAElementBridge extends PDFAElementBridge {
292
293
        private PDFRenderer renderer;
294
295
        public LinkBackAElementBridge(PDFRenderer renderer) {
296
            this.renderer = renderer;
297
        }
298
299
        /** {@inheritDoc} */
300
        protected GraphicsNode instantiateGraphicsNode() {
301
            return new LinkBackPDFANode(this.renderer);
302
        }
303
304
    }
305
306
    private class LinkBackPDFANode extends PDFANode {
307
308
        private PDFRenderer renderer;
309
310
        public LinkBackPDFANode(PDFRenderer renderer) {
311
            this.renderer = renderer;
312
        }
313
314
        /** {@inheritDoc} */
315
        protected boolean generateFragmentLink(Rectangle2D bounds, PDFGraphics2D pdfg) {
316
            assert getDestination().charAt(0) == '#';
317
            boolean annotsAllowed = renderer.pdfDoc.getProfile().isAnnotationAllowed();
318
            if (!annotsAllowed) {
319
                return false;
320
            }
321
322
            String target = getDestination().substring(1);
323
            Shape b = pdfg.getTransform().createTransformedShape(bounds);
324
            b = this.getOnPageTransform().createTransformedShape(b);
325
326
            renderer.renderInternalLink(b.getBounds2D(), target);
327
            return true;
328
        }
329
330
    }
279
}
331
}
(-)src/java/org/apache/fop/svg/PDFAElementBridge.java (-5 / +4 lines)
Lines 21-34 Link Here
21
21
22
import java.awt.geom.AffineTransform;
22
import java.awt.geom.AffineTransform;
23
23
24
import org.w3c.dom.Element;
25
import org.w3c.dom.svg.SVGAElement;
26
24
import org.apache.batik.bridge.AbstractGraphicsNodeBridge;
27
import org.apache.batik.bridge.AbstractGraphicsNodeBridge;
25
import org.apache.batik.bridge.BridgeContext;
28
import org.apache.batik.bridge.BridgeContext;
26
27
import org.apache.batik.gvt.GraphicsNode;
29
import org.apache.batik.gvt.GraphicsNode;
28
30
29
import org.w3c.dom.Element;
30
import org.w3c.dom.svg.SVGAElement;
31
32
/**
31
/**
33
 * Bridge class for the <a> element.
32
 * Bridge class for the <a> element.
34
 *
33
 *
Lines 83-89 Link Here
83
    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
82
    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
84
        PDFANode aNode = (PDFANode)super.createGraphicsNode(ctx, e);
83
        PDFANode aNode = (PDFANode)super.createGraphicsNode(ctx, e);
85
        aNode.setDestination(((SVGAElement)e).getHref().getBaseVal());
84
        aNode.setDestination(((SVGAElement)e).getHref().getBaseVal());
86
        aNode.setTransform(transform);
85
        aNode.setOnPageTransform(transform);
87
        return aNode;
86
        return aNode;
88
    }
87
    }
89
88
(-)src/java/org/apache/fop/svg/PDFANode.java (-10 / +44 lines)
Lines 19-33 Link Here
19
19
20
package org.apache.fop.svg;
20
package org.apache.fop.svg;
21
21
22
import org.apache.batik.gvt.CompositeGraphicsNode;
23
24
import java.awt.Graphics2D;
22
import java.awt.Graphics2D;
25
import java.awt.Shape;
23
import java.awt.Shape;
24
import java.awt.geom.AffineTransform;
26
import java.awt.geom.Rectangle2D;
25
import java.awt.geom.Rectangle2D;
27
import java.awt.geom.AffineTransform;
28
29
import java.util.StringTokenizer;
26
import java.util.StringTokenizer;
30
27
28
import org.apache.batik.gvt.CompositeGraphicsNode;
29
31
/**
30
/**
32
 * A graphics node that represents an image described as a graphics node.
31
 * A graphics node that represents an image described as a graphics node.
33
 *
32
 *
Lines 35-41 Link Here
35
 */
34
 */
36
public class PDFANode extends CompositeGraphicsNode {
35
public class PDFANode extends CompositeGraphicsNode {
37
    private String destination;
36
    private String destination;
38
    private AffineTransform transform;
37
    private AffineTransform onPageTransform;
39
38
40
    /**
39
    /**
41
     * Constructs a new empty <tt>PDFANode</tt>.
40
     * Constructs a new empty <tt>PDFANode</tt>.
Lines 52-65 Link Here
52
    }
51
    }
53
52
54
    /**
53
    /**
55
     * Set the current transform of this node.
54
     * Returns the destination value for the node.
55
     * @return the destination
56
     */
57
    public String getDestination() {
58
        return this.destination;
59
    }
60
61
    /**
62
     * Set the "on-page" transform of this node. This corrects the placement of the link hot-zones
63
     * with respect of the SVG graphic on the page.
56
     * @param tf the transform
64
     * @param tf the transform
57
     */
65
     */
58
    public void setTransform(AffineTransform tf) {
66
    public void setOnPageTransform(AffineTransform tf) {
59
        transform = tf;
67
        this.onPageTransform = tf;
60
    }
68
    }
61
69
62
    /**
70
    /**
71
     * Returns the "on-page" transform of this node.
72
     * See {@code #setOnPageTransform(AffineTransform)} for details.
73
     * @return the "on-page" transform
74
     */
75
    public AffineTransform getOnPageTransform() {
76
        return this.onPageTransform;
77
    }
78
79
    /**
63
     * Paints this node if visible.
80
     * Paints this node if visible.
64
     *
81
     *
65
     * @param g2d the Graphics2D to use
82
     * @param g2d the Graphics2D to use
Lines 104-112 Link Here
104
                    } catch (Exception e) {
121
                    } catch (Exception e) {
105
                        //TODO Move this to setDestination() and throw an IllegalArgumentException
122
                        //TODO Move this to setDestination() and throw an IllegalArgumentException
106
                        e.printStackTrace();
123
                        e.printStackTrace();
124
                        return;
107
                    }
125
                    }
108
                    Rectangle2D destRect = new Rectangle2D.Float(x, y, width, height);
126
                    Rectangle2D destRect = new Rectangle2D.Float(x, y, width, height);
109
                    destRect = transform.createTransformedShape(destRect).getBounds();
127
                    destRect = getOnPageTransform().createTransformedShape(destRect).getBounds();
110
                    // these numbers need conversion to current
128
                    // these numbers need conversion to current
111
                    // svg position and scaled for the page
129
                    // svg position and scaled for the page
112
                    x = (float)destRect.getX();
130
                    x = (float)destRect.getX();
Lines 116-126 Link Here
116
134
117
                    destination = "" + x + " " + y + " "
135
                    destination = "" + x + " " + y + " "
118
                                  + (x + width) + " " + (y + height);
136
                                  + (x + width) + " " + (y + height);
137
                } else if (destination.startsWith("#")) {
138
                    if (generateFragmentLink(getBounds(), pdfg)) {
139
                        return; //Returns early if the method indicated that it has generated a link
140
                    }
119
                }
141
                }
120
                pdfg.addLink(getBounds(), transform, destination, type);
142
                pdfg.addLink(getBounds(), getOnPageTransform(), destination, type);
121
            }
143
            }
122
        }
144
        }
123
    }
145
    }
124
146
147
    /**
148
     * Generates a link for a fragment reference. By default, it does nothing. Subclasses can
149
     * generate links to objects (ex. in XSL-FO) identified by the fragment reference.
150
     * @param bounds the boundaries of the hot zone
151
     * @param pdfg the PDFGraphics2D object
152
     * @return true if it has generated a link for the fragment reference
153
     */
154
    protected boolean generateFragmentLink(Rectangle2D bounds, PDFGraphics2D pdfg) {
155
        //nop
156
        return false;
157
    }
158
125
}
159
}
126
160
(-)src/java/org/apache/fop/svg/PDFBridgeContext.java (-1 / +9 lines)
Lines 155-161 Link Here
155
                    "org.apache.batik.bridge.svg12.SVGFlowRootElementBridge");
155
                    "org.apache.batik.bridge.svg12.SVGFlowRootElementBridge");
156
        }
156
        }
157
157
158
        PDFAElementBridge pdfAElementBridge = new PDFAElementBridge();
158
        PDFAElementBridge pdfAElementBridge = createPDFAElementBridge();
159
        if (linkTransform != null) {
159
        if (linkTransform != null) {
160
            pdfAElementBridge.setCurrentTransform(linkTransform);
160
            pdfAElementBridge.setCurrentTransform(linkTransform);
161
        } else {
161
        } else {
Lines 166-171 Link Here
166
        putBridge(new PDFImageElementBridge());
166
        putBridge(new PDFImageElementBridge());
167
    }
167
    }
168
168
169
    /**
170
     * Creates the "a" element bridge for the bridge context.
171
     * @return the element bridge
172
     */
173
    protected PDFAElementBridge createPDFAElementBridge() {
174
        return new PDFAElementBridge();
175
    }
176
169
    // Make sure any 'sub bridge contexts' also have our bridges.
177
    // Make sure any 'sub bridge contexts' also have our bridges.
170
    //TODO There's no matching method in the super-class here
178
    //TODO There's no matching method in the super-class here
171
    public BridgeContext createBridgeContext() {
179
    public BridgeContext createBridgeContext() {

Return to bug 45759