You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by sp...@apache.org on 2007/09/25 10:41:56 UTC

svn commit: r579125 [3/3] - in /xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking: ./ src/documentation/ src/documentation/content/ src/documentation/content/xdocs/trunk/ src/java/org/apache/fop/apps/ src/java/org/apache/fop/area/ src/java/o...

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFRoot.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFRoot.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFRoot.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFRoot.java Tue Sep 25 01:41:51 2007
@@ -20,7 +20,6 @@
 package org.apache.fop.pdf;
 
 import java.util.List;
-import java.util.ArrayList;
 
 /**
  * class representing a Root (/Catalog) object
@@ -63,11 +62,8 @@
     /** The array of OutputIntents */
     private List outputIntents;
     
-    /**
-     * The referencePDF value of the /Dests object,
-     * if this PDF has a Name Dictionary
-     */
-    private String namesReferencePDF = null;
+    /** the /Dests object, if this PDF has a Names Dictionary */
+    private PDFNames names;
 
     private int pageMode = PAGEMODE_USENONE;
 
@@ -133,12 +129,20 @@
     }
     
     /**
-     * Set the optional Metadata object.
-     * @param meta the Metadata object
-     * @since PDF 1.4
+     * Set the Names object.
+     * @param names the Names object
+     * @since PDF 1.2
+     */
+    public void setNames(PDFNames names) {
+        this.names = names;
+    }
+    
+    /**
+     * @return the Names object if set, null otherwise.
+     * @since PDF 1.2
      */
-    public void setNames(String referencePDF) {
-        this.namesReferencePDF = referencePDF;
+    public PDFNames getNames() {
+        return this.names;
     }
     
     /**
@@ -175,7 +179,7 @@
     public String toPDFString() {
         StringBuffer p = new StringBuffer(128);
         p.append(getObjectID());
-        p.append("<< /Type /Catalog\n/Pages "
+        p.append("<< /Type /Catalog\n /Pages "
                 + this.rootPages.referencePDF()
                 + "\n");
         if (outline != null) {
@@ -197,17 +201,17 @@
                 break;
             }
         }
-        if (getDocumentSafely().getHasDestinations() && namesReferencePDF != null) {
-            p.append(" /Names " + namesReferencePDF + "\n");
+        if (getDocumentSafely().hasDestinations() && getNames() != null) {
+            p.append(" /Names " + getNames().referencePDF() + "\n");
         }
         if (getMetadata() != null 
                 && getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) {
-            p.append("/Metadata " + getMetadata().referencePDF() + "\n");
+            p.append(" /Metadata " + getMetadata().referencePDF() + "\n");
         }
         if (this.outputIntents != null 
                 && this.outputIntents.size() > 0
                 && getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) {
-            p.append("/OutputIntents [");
+            p.append(" /OutputIntents [");
             for (int i = 0, c = this.outputIntents.size(); i < c; i++) {
                 PDFOutputIntent outputIntent = (PDFOutputIntent)this.outputIntents.get(i);
                 if (i > 0) {

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFState.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFState.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFState.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFState.java Tue Sep 25 01:41:51 2007
@@ -301,7 +301,22 @@
     }
 
     /**
-     * Get the grapics state.
+     * Get a copy of the base transform for the page. Used to translate
+     * IPP/BPP values into X,Y positions when positioning is "fixed".
+     *
+     * @return the base transform, or null if the state stack is empty
+     */
+    public AffineTransform getBaseTransform() {
+       if (stateStack.size() == 0) {
+           return null;
+       } else {
+           Data baseData = (Data) stateStack.get(0);
+           return (AffineTransform) baseData.transform.clone();
+       }
+    }
+
+    /**
+     * Get the graphics state.
      * This gets the combination of all graphic states for
      * the current context.
      * This is the graphic state set with the gs operator not

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFStream.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFStream.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/PDFStream.java Tue Sep 25 01:41:51 2007
@@ -57,7 +57,7 @@
      */
     public void add(String s) {
         try {
-            data.getOutputStream().write(s.getBytes());
+            data.getOutputStream().write(PDFDocument.encode(s));
         } catch (IOException ex) {
             //TODO throw the exception and catch it elsewhere
             ex.printStackTrace();

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/AbstractRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/AbstractRenderer.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/AbstractRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/AbstractRenderer.java Tue Sep 25 01:41:51 2007
@@ -165,7 +165,7 @@
     /**
      * @see     org.apache.fop.render.Renderer#processOffDocumentItem(OffDocumentItem)
      */
-    public void processOffDocumentItem(OffDocumentItem oDI) { }
+    public void processOffDocumentItem(OffDocumentItem odi) { }
 
     /** @see org.apache.fop.render.Renderer#getGraphics2DAdapter() */
     public Graphics2DAdapter getGraphics2DAdapter() {

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/Renderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/Renderer.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/Renderer.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/Renderer.java Tue Sep 25 01:41:51 2007
@@ -113,9 +113,9 @@
      * document (e.g., PDF bookmarks).  Note - not all renderers will process
      * all off-document items.
      *
-     * @param ext  The extension element to be rendered
+     * @param odi  The off-document item to be rendered
      */
-    void processOffDocumentItem(OffDocumentItem ext);
+    void processOffDocumentItem(OffDocumentItem odi);
 
     /**
      * @return the adapter for painting Java2D images (or null if not supported)

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/bitmap/PNGRenderer.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/bitmap/PNGRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/bitmap/PNGRenderer.java Tue Sep 25 01:41:51 2007
@@ -20,10 +20,6 @@
 package org.apache.fop.render.bitmap;
 
 import java.awt.image.RenderedImage;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 
@@ -33,7 +29,6 @@
 
 import org.apache.commons.io.IOUtils;
 
-import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.MimeConstants;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.render.java2d.Java2DRenderer;
@@ -51,14 +46,11 @@
     /** The file extension expected for PNG files */
     private static final String PNG_FILE_EXTENSION = "png";
 
-    /** The file syntax prefix, eg. "page" will output "page1.png" etc */
-    private String filePrefix;
-
-    /** The output directory where images are to be written */
-    private File outputDir;
-
     /** The OutputStream for the first Image */
     private OutputStream firstOutputStream;
+    
+    /** Helper class for generating multiple files */
+    private MultiFileRenderingUtil multiFileUtil;
 
     /** @see org.apache.fop.render.AbstractRenderer */
     public String getMimeType() {
@@ -68,54 +60,11 @@
     /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
     public void startRenderer(OutputStream outputStream) throws IOException {
         log.info("rendering areas to PNG");
-        setOutputDirectory();
+        multiFileUtil = new MultiFileRenderingUtil(PNG_FILE_EXTENSION, 
+                    getUserAgent().getOutputFile());
         this.firstOutputStream = outputStream;
     }
 
-    /**
-     * Sets the output directory, either from the outfile specified on the
-     * command line, or from the directory specified in configuration file.
-     * Also sets the file name syntax, eg. "page".
-     * The file name must not have an extension, or must have extension "png",
-     * and its last period must not be at the start (empty file prefix).
-     * 
-     * @throws IOException if an invalid output file name was specified
-     *                     (e.g., with an extension other than '.png')
-     */
-    private void setOutputDirectory() throws IOException {
-
-        // the file provided on the command line
-        File f = getUserAgent().getOutputFile();
-        if (f == null) {
-            //No filename information available. Only the first page will be rendered.
-            outputDir = null;
-            filePrefix = null;
-        } else {
-            outputDir = f.getParentFile();
-
-            // extracting file name syntax
-            String s = f.getName();
-            int i = s.lastIndexOf(".");
-            if (i > 0) {
-                // Make sure that the file extension was "png"
-                String extension = s.substring(i + 1).toLowerCase();
-                if (!PNG_FILE_EXTENSION.equals(extension)) {
-                    throw new IOException("Invalid file extension ('"
-                                          + extension + "') specified");
-                }
-            } else if (i == -1) {
-                i = s.length();
-            } else { // i == 0
-                throw new IOException("Invalid file name ('"
-                                      + s + "') specified");
-            }
-            if (s.charAt(i - 1) == '1') {
-                i--; // getting rid of the "1"
-            }
-            filePrefix = s.substring(0, i);
-        }
-    }
-
     /** @see org.apache.fop.render.Renderer#stopRenderer() */
     public void stopRenderer() throws IOException {
 
@@ -131,23 +80,14 @@
             }
             try {
                 // Do the rendering: get the image for this page
-                RenderedImage image = (RenderedImage) getPageImage((PageViewport) pageViewportList
-                        .get(i));
+                PageViewport pv = (PageViewport)pageViewportList.get(i);
+                RenderedImage image = (RenderedImage)getPageImage(pv);
     
                 // Encode this image
-                log.debug("Encoding page " + (i + 1));
-                ImageWriterParams params = new ImageWriterParams();
-                params.setResolution(Math.round(userAgent.getTargetResolution()));
-                
-                // Encode PNG image
-                ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor(getMimeType());
-                if (writer == null) {
-                    throw new IOException("Could not get an ImageWriter to produce " 
-                            + getMimeType() + ". The most likely explanation for this is a class"
-                            + " loading problem.");
+                if (log.isDebugEnabled()) {
+                    log.debug("Encoding page " + (i + 1));
                 }
-                log.debug("Writing image using " + writer.getClass().getName());
-                writer.writeImage(image, os, params);
+                writeImage(os, image);
             } finally {
                 //Only close self-created OutputStreams
                 if (os != firstOutputStream) {
@@ -157,29 +97,36 @@
         }
     }
 
+    private void writeImage(OutputStream os, RenderedImage image) throws IOException {
+        ImageWriterParams params = new ImageWriterParams();
+        params.setResolution(Math.round(userAgent.getTargetResolution()));
+        
+        // Encode PNG image
+        ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor(getMimeType());
+        if (writer == null) {
+            throw new IOException("Could not get an ImageWriter to produce " 
+                    + getMimeType() + ". The most likely explanation for this is a class"
+                    + " loading problem.");
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("Writing image using " + writer.getClass().getName());
+        }
+        writer.writeImage(image, os, params);
+    }
+
     /**
-     * Builds the OutputStream corresponding to this page
-     * @param 0-based pageNumber
+     * Returns the OutputStream corresponding to this page
+     * @param pageNumber 0-based page number
      * @return the corresponding OutputStream
+     * @throws IOException In case of an I/O error
      */
-    private OutputStream getCurrentOutputStream(int pageNumber) {
+    protected OutputStream getCurrentOutputStream(int pageNumber) throws IOException {
 
         if (pageNumber == 0) {
             return firstOutputStream;
-        }
-
-        if (filePrefix == null) {
-            return null;
         } else {
-            File f = new File(outputDir,
-                    filePrefix + (pageNumber + 1) + "." + PNG_FILE_EXTENSION);
-            try {
-                OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
-                return os;
-            } catch (FileNotFoundException e) {
-                new FOPException("Can't build the OutputStream\n" + e);
-                return null;
-            }
+            return multiFileUtil.createOutputStream(pageNumber);
         }
+
     }
 }

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/pdf/PDFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/pdf/PDFRenderer.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/pdf/PDFRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/pdf/PDFRenderer.java Tue Sep 25 01:41:51 2007
@@ -24,6 +24,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URL;
+import java.awt.geom.Point2D;
 import java.awt.Color;
 import java.awt.color.ColorSpace;
 import java.awt.color.ICC_Profile;
@@ -48,6 +49,8 @@
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
 import org.apache.fop.area.CTM;
 import org.apache.fop.area.LineArea;
 import org.apache.fop.area.OffDocumentExtensionAttachment;
@@ -60,6 +63,7 @@
 import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.area.inline.Image;
 import org.apache.fop.area.inline.Leader;
+import org.apache.fop.area.inline.InlineArea;
 import org.apache.fop.area.inline.InlineParent;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.area.inline.SpaceArea;
@@ -69,17 +73,20 @@
 import org.apache.fop.image.FopImage;
 import org.apache.fop.image.ImageFactory;
 import org.apache.fop.image.XMLImage;
+import org.apache.fop.pdf.PDFAction;
 import org.apache.fop.pdf.PDFAMode;
 import org.apache.fop.pdf.PDFAnnotList;
 import org.apache.fop.pdf.PDFColor;
 import org.apache.fop.pdf.PDFConformanceException;
-import org.apache.fop.pdf.PDFDestination;
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFEncryptionManager;
 import org.apache.fop.pdf.PDFEncryptionParams;
+import org.apache.fop.pdf.PDFFactory;
 import org.apache.fop.pdf.PDFFilterList;
+import org.apache.fop.pdf.PDFGoTo;
 import org.apache.fop.pdf.PDFICCBasedColorSpace;
 import org.apache.fop.pdf.PDFICCStream;
+import org.apache.fop.pdf.PDFGoTo;
 import org.apache.fop.pdf.PDFInfo;
 import org.apache.fop.pdf.PDFLink;
 import org.apache.fop.pdf.PDFMetadata;
@@ -164,16 +171,35 @@
     protected Map pages = null;
 
     /**
-     * Page references are stored using the PageViewport as the key
-     * when a reference is made the PageViewport is used
-     * for pdf this means we need the pdf page reference
+     * Maps unique PageViewport key to PDF page reference
      */
     protected Map pageReferences = new java.util.HashMap();
 
-    /** Page viewport references */
+    /**
+     *  Maps unique PageViewport key back to PageViewport itself
+     */
     protected Map pvReferences = new java.util.HashMap();
 
     /**
+     * Maps XSL-FO element IDs to their on-page XY-positions
+     * Must be used in conjunction with the page reference to fully specify the PDFGoTo details
+     */
+    protected Map idPositions = new java.util.HashMap();
+
+    /**
+     * Maps XSL-FO element IDs to PDFGoTo objects targeting the corresponding areas
+     * These objects may not all be fully filled in yet
+     */
+    protected Map idGoTos = new java.util.HashMap();
+
+    /**
+     * The PDFGoTos in idGoTos that are not complete yet
+     */
+    protected List unfinishedGoTos = new java.util.ArrayList();
+    // can't use a Set because PDFGoTo.equals returns true if the target is the same,
+    // even if the object number differs
+
+    /**
      * The output stream to write the document to
      */
     protected OutputStream ostream;
@@ -197,7 +223,12 @@
      * the current page to add annotations to
      */
     protected PDFPage currentPage;
-    
+
+    /**
+     * the current page's PDF reference string (to avoid numerous function calls)
+     */
+    protected String currentPageRef;
+
     /** the (optional) encryption parameters */
     protected PDFEncryptionParams encryptionParams;
 
@@ -479,9 +510,34 @@
     }
 
     /**
+     * Checks if there are any unfinished PDFGoTos left in the list and resolves them
+     * to a default position on the page. Logs a warning, as this should not happen.
+     */
+    protected void finishOpenGoTos() {
+        int count = unfinishedGoTos.size();
+        if (count > 0) {
+            // TODO : page height may not be the same for all targeted pages
+            Point2D.Float defaultPos = new Point2D.Float(0f, pageHeight / 1000f);  // top-o-page
+            while (!unfinishedGoTos.isEmpty()) {
+                PDFGoTo gt = (PDFGoTo) unfinishedGoTos.get(0);
+                finishIDGoTo(gt, defaultPos);
+            }
+            boolean one = count == 1;
+            String pl = one ? ""    : "s";
+            String ww = one ? "was" : "were";
+            String ia = one ? "is"  : "are";
+            log.warn("" + count + " link target" + pl + " could not be fully resolved and "
+                        + ww + " now point to the top of the page or "
+                        + ia + " dysfunctional.");  // dysfunctional if pageref is null
+        }
+    }
+
+    /**
      * @see org.apache.fop.render.Renderer#stopRenderer()
      */
     public void stopRenderer() throws IOException {
+        finishOpenGoTos();
+
         pdfDoc.getResources().addFonts(pdfDoc, fontInfo);
         pdfDoc.outputTrailer(ostream);
 
@@ -498,6 +554,9 @@
         currentPage = null;
         currentState = null;
         currentFontName = "";
+
+        idPositions.clear();
+        idGoTos.clear();
     }
 
     /**
@@ -512,19 +571,11 @@
      * @see org.apache.fop.render.Renderer#processOffDocumentItem(OffDocumentItem)
      */
     public void processOffDocumentItem(OffDocumentItem odi) {
-        // render Destinations
         if (odi instanceof DestinationData) {
-            PDFDestination destination = pdfDoc.getFactory().makeDestination((DestinationData) odi);
-            PageViewport pv = destination.getPageViewport();
-            String dest = (String)pageReferences.get(pv.getKey());
-            Rectangle2D bounds = pv.getViewArea();
-            double h = bounds.getHeight();
-            float yoffset = (float)h / 1000f;
-            String gtRef = pdfDoc.getFactory().getGoToReference(dest, yoffset);
-            destination.setGoToReference(gtRef);
-        }
-        // render Bookmark-Tree
-        else if (odi instanceof BookmarkData) {
+            // render Destinations
+            renderDestination((DestinationData) odi);
+        } else if (odi instanceof BookmarkData) {
+            // render Bookmark-Tree
             renderBookmarkTree((BookmarkData) odi);
         } else if (odi instanceof OffDocumentExtensionAttachment) {
             ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)odi).getAttachment();
@@ -534,6 +585,21 @@
         }
     }
 
+    private void renderDestination(DestinationData dd) {
+        String targetID = dd.getIDRef();
+        if (targetID != null && targetID.length() > 0) {
+            PageViewport pv = dd.getPageViewport();
+            if (pv == null) {
+                log.warn("Unresolved destination item received: " + dd.getIDRef());
+            }
+            PDFGoTo gt = getPDFGoToForID(targetID, pv.getKey());
+            pdfDoc.getFactory().makeDestination(
+                    dd.getIDRef(), gt.makeReference());
+        } else {
+            log.warn("DestinationData item with null or empty IDRef received.");
+        }
+    }
+
     /**
      * Renders a Bookmark-Tree object
      * @param bookmarks the BookmarkData object containing all the Bookmark-Items
@@ -545,36 +611,34 @@
         }
     }
 
-    private void renderBookmarkItem(BookmarkData bookmarkItem, 
-            PDFOutline parentBookmarkItem) {
+    private void renderBookmarkItem(BookmarkData bookmarkItem,
+                                    PDFOutline parentBookmarkItem) {
         PDFOutline pdfOutline = null;
-        PageViewport pv = bookmarkItem.getPageViewport();
-        if (pv != null) {
-            Rectangle2D bounds = pv.getViewArea();
-            double h = bounds.getHeight();
-            float yoffset = (float)h / 1000f;
-            String intDest = (String)pageReferences.get(pv.getKey());
-            if (parentBookmarkItem == null) {
-                PDFOutline outlineRoot = pdfDoc.getOutlineRoot();
-                pdfOutline = pdfDoc.getFactory().makeOutline(outlineRoot,
-                                        bookmarkItem.getBookmarkTitle(), 
-                                        intDest, yoffset,
-                                        bookmarkItem.showChildItems());
+
+        String targetID = bookmarkItem.getIDRef();
+        if (targetID != null && targetID.length() > 0) {
+            PageViewport pv = bookmarkItem.getPageViewport();
+            if (pv != null) {
+                String pvKey = pv.getKey();
+                PDFGoTo gt = getPDFGoToForID(targetID, pvKey);
+                // create outline object:
+                PDFOutline parent = parentBookmarkItem != null
+                    ? parentBookmarkItem
+                    : pdfDoc.getOutlineRoot();
+                pdfOutline = pdfDoc.getFactory().makeOutline(parent,
+                        bookmarkItem.getBookmarkTitle(), gt, bookmarkItem.showChildItems());
             } else {
-                pdfOutline = pdfDoc.getFactory().makeOutline(parentBookmarkItem,
-                                        bookmarkItem.getBookmarkTitle(), 
-                                        intDest, yoffset, 
-                                        bookmarkItem.showChildItems());
+                log.warn("Bookmark with IDRef \"" + targetID + "\" has a null PageViewport.");
             }
         } else {
-            log.warn("Unresolved bookmark item received: " + bookmarkItem.getIDRef());
+            log.warn("Bookmark item with null or empty IDRef received.");
         }
 
         for (int i = 0; i < bookmarkItem.getCount(); i++) {
             renderBookmarkItem(bookmarkItem.getSubData(i), pdfOutline);
         }
     }
-    
+
     private void renderXMPMetadata(XMPMetadata metadata) {
         Metadata docXMP = metadata.getMetadata();
         Metadata fopXMP = PDFMetadata.createXMPFromUserAgent(pdfDoc);
@@ -707,6 +771,8 @@
         } else {
             setupPage(page);
         }
+        currentPageRef = currentPage.referencePDF();
+
         Rectangle2D bounds = page.getViewArea();
         double h = bounds.getHeight();
         pageHeight = (int) h;
@@ -1089,6 +1155,188 @@
     }
 
     /**
+     * Returns area's id if it is the first area in the document with that id 
+     * (i.e. if the area qualifies as a link target).
+     * Otherwise, or if the area has no id, null is returned.
+     *
+     * NOTE : area must be on currentPageViewport, otherwise result may be wrong!
+     *
+     * @param area the area for which to return the id
+     */
+    protected String getTargetableID(Area area) {
+        String id = (String) area.getTrait(Trait.PROD_ID);
+        if (id == null || id.length() == 0
+            || !currentPageViewport.isFirstWithID(id)
+            || idPositions.containsKey(id)) {
+            return null;
+        } else {
+            return id;
+        }
+    }
+
+    /**
+     * Set XY position in the PDFGoTo and add it to the PDF trailer.
+     *
+     * @param gt the PDFGoTo object
+     * @param position the X,Y position to set
+     */
+    protected void finishIDGoTo(PDFGoTo gt, Point2D.Float position) {
+        gt.setPosition(position);
+        pdfDoc.addTrailerObject(gt);
+        unfinishedGoTos.remove(gt);
+    }
+
+    /**
+     * Set page reference and XY position in the PDFGoTo and add it to the PDF trailer.
+     *
+     * @param gt the PDFGoTo object
+     * @param pdfPageRef the PDF reference string of the target page object
+     * @param position the X,Y position to set
+     */
+    protected void finishIDGoTo(PDFGoTo gt, String pdfPageRef, Point2D.Float position) {
+        gt.setPageReference(pdfPageRef);
+        finishIDGoTo(gt, position);
+    }
+
+    /**
+     * Get a PDFGoTo pointing to the given id. Create one if necessary.
+     * It is possible that the PDFGoTo is not fully resolved yet. In that case
+     * it must be completed (and added to the PDF trailer) later.
+     *
+     * @param targetID the target id of the PDFGoTo
+     * @param pvKey the unique key of the target PageViewport
+     *
+     * @return the PDFGoTo that was found or created
+     */
+    protected PDFGoTo getPDFGoToForID(String targetID, String pvKey) {
+        // Already a PDFGoTo present for this target? If not, create.
+        PDFGoTo gt = (PDFGoTo) idGoTos.get(targetID);
+        if (gt == null) {
+            String pdfPageRef = (String) pageReferences.get(pvKey);
+            Point2D.Float position = (Point2D.Float) idPositions.get(targetID);
+            // can the GoTo already be fully filled in?
+            if (pdfPageRef != null && position != null) {
+                // getPDFGoTo shares PDFGoTo objects as much as possible.
+                // It also takes care of assignObjectNumber and addTrailerObject.
+                gt = pdfDoc.getFactory().getPDFGoTo(pdfPageRef, position);
+            } else {
+                // Not complete yet, can't use getPDFGoTo:
+                gt = new PDFGoTo(pdfPageRef);
+                pdfDoc.assignObjectNumber(gt);
+                // pdfDoc.addTrailerObject() will be called later, from finishIDGoTo()
+                unfinishedGoTos.add(gt);
+            }
+            idGoTos.put(targetID, gt);
+        }
+        return gt;
+    }
+
+    /**
+     * Saves id's absolute position on page for later retrieval by PDFGoTos
+     *
+     * @param id the id of the area whose position must be saved
+     * @param pdfPageRef the PDF page reference string
+     * @param relativeIPP the *relative* IP position in millipoints
+     * @param relativeBPP the *relative* BP position in millipoints
+     * @param tf the transformation to apply once the relative positions have been 
+     *           converted to points
+     */
+    protected void saveAbsolutePosition(String id, String pdfPageRef,
+                                        int relativeIPP, int relativeBPP, AffineTransform tf) {
+        Point2D.Float position = new Point2D.Float(relativeIPP / 1000f, relativeBPP / 1000f);
+        tf.transform(position, position);
+        idPositions.put(id, position);
+        // is there already a PDFGoTo waiting to be completed?
+        PDFGoTo gt = (PDFGoTo) idGoTos.get(id);
+        if (gt != null) {
+            finishIDGoTo(gt, pdfPageRef, position);
+        }
+/*
+        // The code below auto-creates a named destination for every id in the document.
+        // This should probably be controlled by a user-configurable setting, as it may
+        // make the PDF file grow noticeably.
+        // *** NOT YET WELL-TESTED ! ***
+        if (true) {
+            PDFFactory factory = pdfDoc.getFactory();
+            if (gt == null) {
+                gt = factory.getPDFGoTo(pdfPageRef, position);
+                idGoTos.put(id, gt);  // so others can pick it up too
+            }
+            factory.makeDestination(id, gt.referencePDF(), currentPageViewport);
+            // Note: using currentPageViewport is only correct if the id is indeed on
+            // the current PageViewport. But even if incorrect, it won't interfere with
+            // what gets created in the PDF.
+            // For speedup, we should also create a lookup map id -> PDFDestination
+        }
+*/
+    }
+
+    /**
+     * Saves id's absolute position on page for later retrieval by PDFGoTos,
+     * using the currently valid transformation and the currently valid PDF page reference
+     *
+     * @param id the id of the area whose position must be saved
+     * @param relativeIPP the *relative* IP position in millipoints
+     * @param relativeBPP the *relative* BP position in millipoints
+     */
+    protected void saveAbsolutePosition(String id, int relativeIPP, int relativeBPP) {
+        saveAbsolutePosition(id, currentPageRef, 
+                             relativeIPP, relativeBPP, currentState.getTransform());
+    }
+
+    /**
+     * If the given block area is a possible link target, its id + absolute position will 
+     * be saved. The saved position is only correct if this function is called at the very 
+     * start of renderBlock!
+     *
+     * @param block the block area in question
+     */
+    protected void saveBlockPosIfTargetable(Block block) {
+        String id = getTargetableID(block);
+        if (id != null) {
+            // FIXME: Like elsewhere in the renderer code, absolute and relative
+            //        directions are happily mixed here. This makes sure that the
+            //        links point to the right location, but it is not correct.
+            int ipp = block.getXOffset();
+            int bpp = block.getYOffset() + block.getSpaceBefore();
+            int positioning = block.getPositioning();
+            if (!(positioning == Block.FIXED || positioning == Block.ABSOLUTE)) {
+                ipp += currentIPPosition;
+                bpp += currentBPPosition;
+            }
+            AffineTransform tf = positioning == Block.FIXED
+                ? currentState.getBaseTransform()
+                : currentState.getTransform();
+            saveAbsolutePosition(id, currentPageRef, ipp, bpp, tf);
+        }
+    }
+
+    /**
+     * If the given inline area is a possible link target, its id + absolute position will
+     * be saved. The saved position is only correct if this function is called at the very
+     * start of renderInlineArea!
+     *
+     * @param inlineArea the inline area in question
+     */
+    protected void saveInlinePosIfTargetable(InlineArea inlineArea) {
+        String id = getTargetableID(inlineArea);
+        if (id != null) {
+            int extraMarginBefore = 5000; // millipoints
+            int ipp = currentIPPosition;
+            int bpp = currentBPPosition + inlineArea.getOffset() - extraMarginBefore;
+            saveAbsolutePosition(id, ipp, bpp);
+        }
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderBlock(Block)
+     */
+    protected void renderBlock(Block block) {
+        saveBlockPosIfTargetable(block);
+        super.renderBlock(block);
+    }
+
+    /**
      * @see org.apache.fop.render.AbstractRenderer#renderLineArea(LineArea)
      */
     protected void renderLineArea(LineArea line) {
@@ -1097,53 +1345,88 @@
     }
 
     /**
+     * @see org.apache.fop.render.AbstractRenderer#renderInlineArea(InlineArea)
+     */
+    protected void renderInlineArea(InlineArea inlineArea) {
+        saveInlinePosIfTargetable(inlineArea);
+        super.renderInlineArea(inlineArea);
+    }
+
+    /**
      * Render inline parent area.
      * For pdf this handles the inline parent area traits such as
      * links, border, background.
      * @param ip the inline parent area
      */
     public void renderInlineParent(InlineParent ip) {
-        float start = currentIPPosition / 1000f;
-        float top = (ip.getOffset() + currentBPPosition) / 1000f;
 
-        float width = ip.getIPD() / 1000f;
-        float height = ip.getBPD() / 1000f;
+        boolean annotsAllowed = pdfDoc.getProfile().isAnnotationAllowed();
+
+        // stuff we only need if a link must be created:
+        Rectangle2D ipRect = null;
+        PDFFactory factory = null;
+        PDFAction action   = null;
+        if (annotsAllowed) {
+            // make sure the rect is determined *before* calling super!
+            int ipp = currentIPPosition;
+            int bpp = currentBPPosition + ip.getOffset();
+            ipRect = new Rectangle2D.Float(ipp / 1000f, bpp / 1000f,
+                                           ip.getIPD() / 1000f, ip.getBPD() / 1000f);
+            AffineTransform transform = currentState.getTransform();
+            ipRect = transform.createTransformedShape(ipRect).getBounds2D();
+
+            factory = pdfDoc.getFactory();
+        }
+
         // render contents
         super.renderInlineParent(ip);
 
-        if (pdfDoc.getProfile().isAnnotationAllowed()) {
-            // place the link over the top
-            Object tr = ip.getTrait(Trait.INTERNAL_LINK);
-            boolean internal = false;
-            String dest = null;
-            float yoffset = 0;
-            if (tr == null) {
-                dest = (String)ip.getTrait(Trait.EXTERNAL_LINK);
+        boolean linkTraitFound = false;
+
+        // try INTERNAL_LINK first
+        Trait.InternalLink intLink = (Trait.InternalLink) ip.getTrait(Trait.INTERNAL_LINK);
+        if (intLink != null) {
+            linkTraitFound = true;
+            String pvKey = intLink.getPVKey();
+            String idRef = intLink.getIDRef();
+            boolean pvKeyOK = pvKey != null && pvKey.length() > 0;
+            boolean idRefOK = idRef != null && idRef.length() > 0;
+            if (pvKeyOK && idRefOK) {
+                if (annotsAllowed) {
+                    action = getPDFGoToForID(idRef, pvKey);
+                }
+            } else if (pvKeyOK) {
+                log.warn("Internal link trait with PageViewport key " + pvKey 
+                         + " contains no ID reference.");
+            } else if (idRefOK) {
+                log.warn("Internal link trait with ID reference " + idRef 
+                         + " contains no PageViewport key.");
             } else {
-                String pvKey = (String)tr;
-                dest = (String)pageReferences.get(pvKey);
-                if (dest != null) {
-                    PageViewport pv = (PageViewport)pvReferences.get(pvKey);
-                    Rectangle2D bounds = pv.getViewArea();
-                    double h = bounds.getHeight();
-                    yoffset = (float)h / 1000f;
-                    internal = true;
+                log.warn("Internal link trait received with neither PageViewport key"
+                         + " nor ID reference.");
+            }
+        }
+
+        // no INTERNAL_LINK, look for EXTERNAL_LINK
+        if (!linkTraitFound) {
+            String extDest = (String) ip.getTrait(Trait.EXTERNAL_LINK);
+            if (extDest != null && extDest.length() > 0) {
+                linkTraitFound = true;
+                if (annotsAllowed) {
+                    action = factory.getExternalAction(extDest);
                 }
             }
-            if (dest != null) {
-                // add link to pdf document
-                Rectangle2D rect = new Rectangle2D.Float(start, top, width, height);
-                // transform rect to absolute coords
-                AffineTransform transform = currentState.getTransform();
-                rect = transform.createTransformedShape(rect).getBounds2D();
-
-                int type = internal ? PDFLink.INTERNAL : PDFLink.EXTERNAL;
-                PDFLink pdflink = pdfDoc.getFactory().makeLink(
-                            rect, dest, type, yoffset);
-                currentPage.addAnnotation(pdflink);
+        }
+
+        // warn if link trait found but not allowed, else create link
+        if (linkTraitFound) {
+            if (!annotsAllowed) {
+                log.warn("Skipping annotation for a link due to PDF profile: " 
+                         + pdfDoc.getProfile());
+            } else if (action != null) {
+                PDFLink pdfLink = factory.makeLink(ipRect, action);
+                currentPage.addAnnotation(pdfLink);
             }
-        } else {
-            log.warn("Skipping annotation for a link due to PDF profile: " + pdfDoc.getProfile());
         }
     }
 
@@ -1199,12 +1482,12 @@
         String s = word.getWord();
         escapeText(s, word.getLetterAdjustArray(), 
                 font, (AbstractTextArea)word.getParentArea(), useMultiByte, pdf);
-        
+
         currentStream.add(pdf.toString());
 
         super.renderWord(word);
     }
-    
+
     /**
      * @see org.apache.fop.render.AbstractRenderer#renderSpace(SpaceArea)
      */
@@ -1223,18 +1506,18 @@
         if (space.isAdjustable()) {
             int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust()
                          - 2 * textArea.getTextLetterSpaceAdjust();
-                    
+
             if (tws != 0) {
                 pdf.append(format(tws / (font.getFontSize() / 1000f)));
                 pdf.append(" ");
             }
         }
-        
+
         currentStream.add(pdf.toString());
 
         super.renderSpace(space);
     }
-    
+
     /**
      * Escapes text according to PDF rules.
      * @param s Text to escape
@@ -1282,9 +1565,9 @@
                 }
             }
             if (letterAdjust != null && i < l - 1) {
-                glyphAdjust -= letterAdjust[i + 1]; 
+                glyphAdjust -= letterAdjust[i + 1];
             }
-            
+
             if (startPending) {
                 pdf.append(startText);
                 startPending = false;
@@ -1309,12 +1592,12 @@
             }
 
             float adjust = glyphAdjust / fontSize;
-            
+
             if (adjust != 0) {
                 pdf.append(endText).append(format(adjust)).append(' ');
                 startPending = true;
             }
-            
+
         }
         if (!startPending) {
             pdf.append(endText);

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/xml/XMLRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/xml/XMLRenderer.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/xml/XMLRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/render/xml/XMLRenderer.java Tue Sep 25 01:41:51 2007
@@ -60,11 +60,13 @@
 import org.apache.fop.area.NormalFlow;
 import org.apache.fop.area.OffDocumentExtensionAttachment;
 import org.apache.fop.area.OffDocumentItem;
+import org.apache.fop.area.BookmarkData;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.area.RegionReference;
 import org.apache.fop.area.RegionViewport;
 import org.apache.fop.area.Span;
 import org.apache.fop.area.Trait;
+import org.apache.fop.area.Trait.InternalLink;
 import org.apache.fop.area.Trait.Background;
 import org.apache.fop.area.inline.Container;
 import org.apache.fop.area.inline.ForeignObject;
@@ -350,6 +352,9 @@
                     addAttribute("font-name", triplet.getName());
                     addAttribute("font-style", triplet.getStyle());
                     addAttribute("font-weight", triplet.getWeight());
+                } else if (clazz.equals(InternalLink.class)) {
+                    InternalLink iLink = (InternalLink)value;
+                    addAttribute(name, iLink.xmlAttribute());
                 } else if (clazz.equals(Background.class)) {
                     Background bkg = (Background)value;
                     //TODO Remove the following line (makes changes in the test checks necessary)
@@ -431,7 +436,9 @@
 
     /** @see org.apache.fop.render.AbstractRenderer#processOffDocumentItem(OffDocumentItem) */
     public void processOffDocumentItem(OffDocumentItem oDI) {
-        if (oDI instanceof OffDocumentExtensionAttachment) {
+        if (oDI instanceof BookmarkData) {
+            renderBookmarkTree((BookmarkData) oDI);
+        } else if (oDI instanceof OffDocumentExtensionAttachment) {
             ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment();
             if (extensionAttachments == null) {
                 extensionAttachments = new java.util.ArrayList();
@@ -444,6 +451,40 @@
     }
 
     /**
+     * Renders a BookmarkTree object
+     * @param bookmarkRoot the BookmarkData object representing the top of the tree
+     */
+    protected void renderBookmarkTree(BookmarkData bookmarkRoot) {
+        if (bookmarkRoot.getWhenToProcess() == OffDocumentItem.END_OF_DOC) {
+            endPageSequence();
+        }
+        /* If this kind of handling is also necessary for other renderers, then
+           better add endPageSequence to the Renderer interface and call it
+           explicitly from model.endDocument() */
+
+        startElement("bookmarkTree");
+        for (int i = 0; i < bookmarkRoot.getCount(); i++) {
+            renderBookmarkItem(bookmarkRoot.getSubData(i));
+        }
+        endElement("bookmarkTree");
+    }
+
+    private void renderBookmarkItem(BookmarkData bm) {
+        atts.clear();
+        addAttribute("title", bm.getBookmarkTitle());
+        addAttribute("show-children", String.valueOf(bm.showChildItems()));
+        PageViewport pv = bm.getPageViewport();
+        String pvKey = pv == null ? null : pv.getKey();
+        addAttribute("internal-link",
+                     InternalLink.makeXMLAttribute(pvKey, bm.getIDRef()));
+        startElement("bookmark", atts);
+        for (int i = 0; i < bm.getCount(); i++) {
+            renderBookmarkItem(bm.getSubData(i));
+        }
+        endElement("bookmark");
+    }
+
+    /**
      * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
      */
     public void startRenderer(OutputStream outputStream)
@@ -480,9 +521,7 @@
      * @see org.apache.fop.render.Renderer#stopRenderer()
      */
     public void stopRenderer() throws IOException {
-        if (startedSequence) {
-            endElement("pageSequence");
-        }
+        endPageSequence();
         endElement("areaTree");
         try {
             handler.endDocument();
@@ -549,9 +588,7 @@
      */
     public void startPageSequence(LineArea seqTitle) {
         handleDocumentExtensionAttachments();
-        if (startedSequence) {
-            endElement("pageSequence");
-        }
+        endPageSequence();  // move this before handleDocumentExtensionAttachments() ?
         startedSequence = true;
         startElement("pageSequence");
         if (seqTitle != null) {
@@ -568,6 +605,16 @@
     }
 
     /**
+     * Tells the renderer to finish the current PageSequence
+     */
+    public void endPageSequence() {
+        if (startedSequence) {
+            endElement("pageSequence");
+        }
+        startedSequence = false;
+    }
+
+    /**
      * @see org.apache.fop.render.AbstractRenderer#renderRegionViewport(RegionViewport)
      */
     protected void renderRegionViewport(RegionViewport port) {
@@ -756,6 +803,24 @@
         startElement("lineArea", atts);
         super.renderLineArea(line);
         endElement("lineArea");
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderInlineArea(InlineArea)
+     */
+    protected void renderInlineArea(InlineArea inlineArea) {
+        atts.clear();
+        if (inlineArea.getClass() == InlineArea.class) {
+            // Generic inline area. This is implemented to allow the 0x0 "dummy"
+            // area generated by fo:wrapper to pass its id.
+            addAreaAttributes(inlineArea);
+            addTraitAttributes(inlineArea);
+            startElement("inline", atts);
+            endElement("inline");
+        } else {
+            super.renderInlineArea(inlineArea);
+            // calls specific renderers for Text, Space, Viewport, etc. etc.
+        }
     }
 
     /**

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGRenderer.java Tue Sep 25 01:41:51 2007
@@ -5,9 +5,9 @@
  * 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.
@@ -19,425 +19,163 @@
 
 package org.apache.fop.render.svg;
 
-import org.apache.fop.apps.FOPException;
-import org.apache.fop.area.CTM;
-import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.LineArea;
-import org.apache.fop.area.inline.ForeignObject;
-import org.apache.fop.area.inline.InlineArea;
-import org.apache.fop.area.inline.Leader;
-import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.svg.SVGUtilities;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.apps.FOUserAgent;
-
-/* org.w3c.dom.Document is not imported to avoid conflict with
-   org.apache.fop.control.Document */
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Text;
-import org.apache.batik.dom.svg.SVGDOMImplementation;
-import org.apache.batik.transcoder.svg2svg.SVGTranscoder;
-import org.apache.batik.transcoder.TranscoderInput;
-import org.apache.batik.transcoder.TranscoderOutput;
-import org.apache.batik.transcoder.TranscoderException;
-
-import java.awt.Color;
-import java.awt.image.BufferedImage;
+import java.awt.Dimension;
+import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
-import java.util.HashMap;
-import java.io.OutputStream;
 import java.io.IOException;
-import java.io.OutputStreamWriter;
+import java.io.OutputStream;
+import java.io.Writer;
 
-import org.apache.fop.render.AbstractRenderer;
-import org.apache.fop.render.XMLHandler;
-import org.apache.fop.render.RendererContext;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.render.bitmap.MultiFileRenderingUtil;
+import org.apache.fop.render.java2d.Java2DGraphicsState;
+import org.apache.fop.render.java2d.Java2DRenderer;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
 
 /**
- * This is the SVG renderer.
+ * <p>
+ * This renderer generates SVG (Scalable Vector Graphics) format.
+ * <p>
+ * This class actually does not render itself, instead it extends
+ * <code>org.apache.fop.render.java2D.Java2DRenderer</code> and uses
+ * Apache Batik's SVGGraphics2D for SVG generation.
  */
-public class SVGRenderer extends AbstractRenderer {
-
-    /** SVG MIME type */
-    public static final String SVG_MIME_TYPE = "image/svg+xml";
-
-    /** SVG namespace */
-    public static final String SVG_NAMESPACE = SVGDOMImplementation.SVG_NAMESPACE_URI;
-
-    private org.w3c.dom.Document svgDocument;
-    private Element svgRoot;
-    private Element currentPageG = null;
-    private Element lastLink = null;
-    private String lastViewbox = null;
+public class SVGRenderer extends Java2DRenderer {
 
-    private Element docDefs = null;
-    private Element pageDefs = null;
-    private Element pagesGroup = null;
+    /** logging instance */
+    private static Log log = LogFactory.getLog(SVGRenderer.class);
 
-    // first sequence title
-    private LineArea docTitle = null;
+    /** The MIME type for the SVG format */
+    public static final String MIME_TYPE = MimeConstants.MIME_SVG;
 
-    private OutputStream ostream;
+    private static final String SVG_FILE_EXTENSION = "svg";
 
-    private float totalWidth = 0;
-    private float totalHeight = 0;
-    private float sequenceWidth = 0;
-    private float sequenceHeight = 0;
+    private OutputStream firstOutputStream;
+    
+    private Document document;
+    
+    private SVGGraphics2D svgGenerator;
 
-    private float pageWidth = 0;
-    private float pageHeight = 0;
-    private int pageNumber = 0;
-
-    private HashMap fontNames = new HashMap();
-    private HashMap fontStyles = new HashMap();
-    private Color saveColor = null;
-
-    /**
-     * The current (internal) font name
-     */
-    private String currentFontName;
-
-    /**
-     * The current font size in millipoints
-     */
-    private int currentFontSize;
-
-    /**
-     * The current colour's red, green and blue component
-     */
-    private float currentRed = 0;
-    private float currentGreen = 0;
-    private float currentBlue = 0;
+    /** Helper class for generating multiple files */
+    private MultiFileRenderingUtil multiFileUtil;
+    
+    /** @see org.apache.fop.render.AbstractRenderer */
+    public String getMimeType() {
+        return MIME_TYPE;
+    }
 
-    /**
-     * Creates a new SVG renderer.
-     */
+    /** Creates TIFF renderer. */
     public SVGRenderer() {
     }
 
     /**
-     * @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
+     * @see org.apache.fop.render.AbstractRenderer#configure(
+     *          org.apache.avalon.framework.configuration.Configuration)
      */
-    public void setUserAgent(FOUserAgent agent) {
-        super.setUserAgent(agent);
-        
-        //Note: This is done here as having two service lookup files in the same IDE project
-        //will end up with one overwriting the other when all sources are compiled in to the
-        //same target directory. Remove this code and add an entry in the XMLHandler resource
-        //file when this renderer exits the sandbox.
-        XMLHandler handler = agent.getXMLHandlerRegistry().getXMLHandler(this, SVG_NAMESPACE);
-        if (handler == null) {
-            agent.getXMLHandlerRegistry().addXMLHandler("org.apache.fop.render.svg.SVGSVGHandler");
-        }
+    public void configure(Configuration cfg) throws ConfigurationException {
     }
 
-    /**
-     * @see org.apache.fop.render.Renderer#setupFontInfo(FontInfo)
-     */
-    public void setupFontInfo(FontInfo fontInfo) {
-        // create a temp Image to test font metrics on
-        BufferedImage fontImage =
-          new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
-        org.apache.fop.render.java2d.FontSetup.setup(fontInfo,
-                fontImage.createGraphics());
+    /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
+    public void startRenderer(OutputStream outputStream) throws IOException {
+        this.firstOutputStream = outputStream;
+        this.multiFileUtil = new MultiFileRenderingUtil(SVG_FILE_EXTENSION, 
+                getUserAgent().getOutputFile());
+        super.startRenderer(this.firstOutputStream);
     }
 
     /**
-     * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
+     * @see org.apache.fop.render.java2d.Java2DRenderer#renderPage(org.apache.fop.area.PageViewport)
      */
-    public void startRenderer(OutputStream outputStream)
-                throws IOException {
-        ostream = outputStream;
-        DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
-        svgDocument = impl.createDocument(SVG_NAMESPACE, "svg", null);
-        svgRoot = svgDocument.getDocumentElement();
-        /*
-        ProcessingInstruction pi =
-            svgDocument.createProcessingInstruction("xml",
-                        " version=\"1.0\" encoding=\"ISO-8859-1\"");
-        svgDocument.insertBefore(pi, svgRoot);
-        */
-
-        docDefs = svgDocument.createElementNS(SVG_NAMESPACE, "defs");
-        svgRoot.appendChild(docDefs);
-
-        pagesGroup = svgDocument.createElementNS(SVG_NAMESPACE, "g");
-        pageDefs = svgDocument.createElementNS(SVG_NAMESPACE, "defs");
-        pagesGroup.appendChild(pageDefs);
-        svgRoot.appendChild(pagesGroup);
+    public void renderPage(PageViewport pageViewport) throws IOException {
+        log.debug("Rendering page: " + pageViewport.getPageNumberString());
+        // Get a DOMImplementation
+        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
 
-    }
+        // Create an instance of org.w3c.dom.Document
+        this.document = domImpl.createDocument(null, "svg", null);
 
-    /**
-     * @see org.apache.fop.render.Renderer#stopRenderer()
-     */
-    public void stopRenderer() throws IOException {
-        totalWidth += sequenceWidth;
-        if (sequenceHeight > totalHeight) {
-            totalHeight = sequenceHeight;
-        }
+        // Create an SVGGeneratorContext to customize SVG generation 
+        SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(this.document);
+        ctx.setComment("Generated by " + userAgent.getProducer() + " with Batik SVG Generator");
+        ctx.setEmbeddedFontsOn(true);
+        
+        // Create an instance of the SVG Generator
+        this.svgGenerator = new SVGGraphics2D(ctx, true);
+        Rectangle2D viewArea = pageViewport.getViewArea();
+        Dimension dim = new Dimension();
+        dim.setSize(viewArea.getWidth() / 1000, viewArea.getHeight() / 1000);
+        this.svgGenerator.setSVGCanvasSize(dim);
 
-        svgRoot.setAttributeNS(null, "width", "" + (totalWidth + 1));
-        svgRoot.setAttributeNS(null, "height", "" + (totalHeight + 1));
-        //svgRoot.setAttributeNS(null, "viewBox", "0 0 " + pageWidth + " " + pageHeight);
-        SVGTranscoder svgT = new SVGTranscoder();
-        TranscoderInput input = new TranscoderInput(svgDocument);
-        TranscoderOutput output =
-          new TranscoderOutput(new OutputStreamWriter(ostream));
+        AffineTransform at = this.svgGenerator.getTransform();
+        this.state = new Java2DGraphicsState(this.svgGenerator, this.fontInfo, at);
         try {
-            svgT.transcode(input, output);
-        } catch (TranscoderException e) {
-            log.error("could not write svg file :" + e.getMessage(), e);
-        }
-        ostream.flush();
-        ostream = null;
-
-        svgDocument = null;
-        svgRoot = null;
-        currentPageG = null;
-        lastLink = null;
-
-        totalWidth = 0;
-        totalHeight = 0;
-
-        pageNumber = 0;
-    }
-
-    /**
-     * @see org.apache.fop.render.Renderer#startPageSequence(LineArea)
-     */
-    public void startPageSequence(LineArea seqTitle) {
-        totalWidth += sequenceWidth;
-        if (sequenceHeight > totalHeight) {
-            totalHeight = sequenceHeight;
-        }
-        sequenceWidth = 0;
-        sequenceHeight = 0;
-        if (seqTitle != null && docTitle == null) {
-            // convert first title to a string and set for svg document title
-            docTitle = seqTitle;
-            String str = convertTitleToString(seqTitle);
-            Element svgTitle = svgDocument.createElementNS(SVG_NAMESPACE, "title");
-            Text strNode = svgDocument.createTextNode(str);
-            svgTitle.appendChild(strNode);
-            svgRoot.insertBefore(svgTitle, svgRoot.getFirstChild());
+            //super.renderPage(pageViewport);
+            renderPageAreas(pageViewport.getPage());            
+        } finally {
+            this.state = null;
         }
+        writeSVGFile(pageViewport.getPageIndex());
+        
+        this.svgGenerator = null;
+        this.document = null;
+        
     }
 
-    /**
-     * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
-     */
-    public void renderPage(PageViewport page) throws IOException, FOPException {
-        float lastWidth = pageWidth;
-        float lastHeight = pageHeight;
-
-        Rectangle2D area = page.getViewArea();
-        pageWidth = (float) area.getWidth() / 1000f;
-        pageHeight = (float) area.getHeight() / 1000f;
-
-        // if there is a link from the last page
-        if (lastLink != null) {
-            lastLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox("
-                                    + totalWidth + ", "
-                                    + sequenceHeight + ", "
-                                    + pageWidth + ", "
-                                    + pageHeight + "))");
-            pagesGroup.appendChild(lastLink);
-        }
-
-        currentPageG = svgDocument.createElementNS(SVG_NAMESPACE, "svg");
-        currentPageG.setAttributeNS(null, "viewbox",
-                                    "0 0 " + (int) pageWidth + " " + (int) pageHeight);
-        currentPageG.setAttributeNS(null, "width",
-                                    "" + ((int) pageWidth + 1));
-        currentPageG.setAttributeNS(null, "height",
-                                    "" + ((int) pageHeight + 1));
-        currentPageG.setAttributeNS(null, "id", "Page-" + pageNumber);
-        currentPageG.setAttributeNS(null, "style", "font-family:sanserif;font-size:12");
-        pageDefs.appendChild(currentPageG);
+    /** @see org.apache.fop.render.Renderer#stopRenderer() */
+    public void stopRenderer() throws IOException {
+        super.stopRenderer();
 
-        if (pageWidth > sequenceWidth) {
-            sequenceWidth = pageWidth;
+        // Cleaning
+        clearViewportList();
+        log.debug("SVG generation complete.");
+    }
+
+    private void writeSVGFile(int pageNumber) throws IOException {
+        log.debug("Writing out SVG file...");
+        // Finally, stream out SVG to the standard output using UTF-8
+        // character to byte encoding
+        boolean useCSS = true; // we want to use CSS style attribute
+        OutputStream out = getCurrentOutputStream(pageNumber);
+        if (out == null) {
+            log.warn("No filename information available."
+                    + " Stopping early after the first page.");
+            return;
         }
-        sequenceHeight += pageHeight;
-
-        Element border =
-          SVGUtilities.createRect(svgDocument, 0, 0, pageWidth,
-                                  pageHeight);
-        border.setAttributeNS(null, "style", "fill:none;stroke:black");
-        currentPageG.appendChild(border);
-
-        // render the page contents
-        super.renderPage(page);
-
-        Element use = svgDocument.createElementNS(SVG_NAMESPACE, "use");
-        use.setAttributeNS(null, "xlink:href", "#Page-" + pageNumber);
-        use.setAttributeNS(null, "x", "" + totalWidth);
-        use.setAttributeNS(null, "y", "" + (sequenceHeight - pageHeight));
-        pagesGroup.appendChild(use);
-
-        Element lastPageLink = svgDocument.createElementNS(SVG_NAMESPACE, "a");
-        if (lastLink != null) {
-            lastPageLink.setAttributeNS(null, "xlink:href", lastViewbox);
-        } else {
-            lastPageLink.setAttributeNS(null, "xlink:href",
-                    "#svgView(viewBox("
-                        + totalWidth + ", "
-                        + (sequenceHeight - pageHeight) + ", "
-                        + pageWidth + ", "
-                        + pageHeight + "))");
+        try {
+            Writer writer = new java.io.OutputStreamWriter(out, "UTF-8");
+            this.svgGenerator.stream(writer, useCSS);
+        } finally {
+            if (out != this.firstOutputStream) {
+                IOUtils.closeQuietly(out);
+            } else {
+                out.flush();
+            }
         }
-        pagesGroup.appendChild(lastPageLink);
-
-        // setup a link to the next page, only added when the
-        // next page is rendered
-        Element rect = SVGUtilities.createRect(svgDocument, totalWidth,
-                    (sequenceHeight - pageHeight), pageWidth / 2, pageHeight);
-        rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden");
-        lastPageLink.appendChild(rect);
-
-        lastLink = svgDocument.createElementNS(SVG_NAMESPACE, "a");
-        rect = SVGUtilities.createRect(svgDocument,
-                                       totalWidth + pageWidth / 2,
-                                       (sequenceHeight - pageHeight), pageWidth / 2, pageHeight);
-        rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden");
-        lastLink.appendChild(rect);
-
-        lastViewbox = "#svgView(viewBox("
-                    + totalWidth + ", "
-                    + (sequenceHeight - pageHeight) + ", "
-                    + pageWidth + ", "
-                    + pageHeight + "))";
-
-        pageNumber++;
-
-    }
-
-    /**
-     * Method renderForeignObject.
-     * @param fo the foreign object
-     */
-    public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
-        org.w3c.dom.Document doc = fo.getDocument();
-        String ns = fo.getNameSpace();
-        renderDocument(doc, ns, pos);
-    }
-
-    /**
-     * Renders an XML document (SVG for example).
-     *
-     * @param doc DOM document representing the XML document
-     * @param ns Namespace for the document
-     * @param pos Position on the page
-     */
-    public void renderDocument(Document doc, String ns, Rectangle2D pos) {
-        RendererContext context;
-        context = new RendererContext(this, getMimeType());
-        context.setUserAgent(userAgent);
-
-        context.setProperty(SVGRendererContextConstants.SVG_DOCUMENT, svgDocument);
-        context.setProperty(SVGRendererContextConstants.SVG_PAGE_G, currentPageG);
-        context.setProperty(SVGRendererContextConstants.XPOS,
-                            new Integer(currentIPPosition + (int)pos.getX()));
-        context.setProperty(SVGRendererContextConstants.YPOS,
-                            new Integer(currentBPPosition + (int)pos.getY()));
-        context.setProperty(SVGRendererContextConstants.WIDTH,
-                            new Integer((int)pos.getWidth()));
-        context.setProperty(SVGRendererContextConstants.HEIGHT,
-                            new Integer((int) pos.getHeight()));
-        
-        renderXML(context, doc, ns);
     }
 
     /**
-     * @see org.apache.fop.render.AbstractRenderer#renderLeader(Leader)
-     */
-    public void renderLeader(Leader area) {
-        String style = "stroke:black;stroke-width:"
-                       + (area.getRuleThickness() / 1000) + ";";
-        switch (area.getRuleStyle()) {
-            case EN_DOTTED:
-                style += "stroke-dasharray:1,1";
-                break;
-            case EN_DASHED:
-                style += "stroke-dasharray:5,1";
-                break;
-            case EN_SOLID:
-                break;
-            case EN_DOUBLE:
-                break;
-            case EN_GROOVE:
-                break;
-            case EN_RIDGE:
-                break;
+     * Returns the OutputStream corresponding to this page
+     * @param pageNumber 0-based page number
+     * @return the corresponding OutputStream
+     * @throws IOException In case of an I/O error
+     */
+    protected OutputStream getCurrentOutputStream(int pageNumber) throws IOException {
+        if (pageNumber == 0) {
+            return firstOutputStream;
+        } else {
+            return multiFileUtil.createOutputStream(pageNumber);
         }
-        Element line = SVGUtilities.createLine(svgDocument,
-                        currentIPPosition / 1000,
-                        (currentBPPosition + area.getOffset()
-                            - area.getRuleThickness() / 2) / 1000,
-                        (currentIPPosition + area.getIPD()) / 1000,
-                        (currentBPPosition + area.getOffset()
-                            - area.getRuleThickness() / 2) / 1000);
-        line.setAttributeNS(null, "style", style);
-        currentPageG.appendChild(line);
-
-        super.renderLeader(area);
-    }
 
-    /**
-     * @see org.apache.fop.render.AbstractRenderer#renderText(TextArea)
-     */
-    public void renderText(TextArea text) {
-        Element textElement = SVGUtilities.createText(svgDocument,
-                                               currentIPPosition / 1000,
-                                               (currentBPPosition + text.getOffset() 
-                                                + text.getBaselineOffset()) / 1000,
-                                               text.getText());
-        currentPageG.appendChild(textElement);
-
-        super.renderText(text);
-    }
-
-    /**
-     * @see org.apache.fop.render.AbstractRenderer#renderCharacter(Character)
-     */
-/* deprecated
-    public void renderCharacter(org.apache.fop.area.inline.Character ch) {
-        Element text = SVGUtilities.createText(svgDocument,
-                                               currentIPPosition / 1000,
-                                               (currentBPPosition + ch.getOffset()
-                                                + ch.getBaselineOffset()) / 1000,
-                                               "" + ch.getChar());
-        currentPageG.appendChild(text);
-
-        super.renderCharacter(ch);
-    }
-*/
-
-    /** @see org.apache.fop.render.AbstractRenderer */
-    public String getMimeType() {
-        return SVG_MIME_TYPE;
     }
-
-    /**
-     * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM, Rectangle2D)
-     */
-    protected void startVParea(CTM ctm, Rectangle2D clippingRect) {
-        // TODO Auto-generated method stub
-    }
-
-    /**
-     * @see org.apache.fop.render.AbstractRenderer#endVParea()
-     */
-    protected void endVParea() {
-        // TODO Auto-generated method stub
-    }
-
-    protected void renderInlineAreaBackAndBorders(InlineArea area) {
-        // TODO Auto-generated method stub
-    }
-
+    
 }
-

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/sandbox/org/apache/fop/render/svg/SVGSVGHandler.java Tue Sep 25 01:41:51 2007
@@ -74,7 +74,7 @@
 
     /** @see org.apache.fop.render.XMLHandler#getNamespace() */
     public String getNamespace() {
-        return SVGRenderer.SVG_NAMESPACE;
+        return SVGRenderer.MIME_TYPE;
     }
 
 

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/status.xml?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/status.xml (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/status.xml Tue Sep 25 01:41:51 2007
@@ -28,6 +28,18 @@
 
   <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>
+      <action context="Code" dev="JM" type="fix" fixes-bug="41434" due-to="Martin Kögler">
+        Fix PDF Genaration for non-ASCII compatible locales.
+      </action>
+      <action context="Code" dev="VH, JM" type="add" importance="high" fixes-bug="36934">
+        Add support for the collapsing-border model in tables.
+      </action>
       <action context="Code" dev="JB" type="add" importance="high">
         Add support for named destinations in PDF.
       </action>

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/disabled-testcases.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/disabled-testcases.xml?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/disabled-testcases.xml (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/disabled-testcases.xml Tue Sep 25 01:41:51 2007
@@ -105,12 +105,6 @@
     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>
     <description>Element lists for lists are created by combining the 

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/hyphenation-testcases/footnote_in_inline.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/hyphenation-testcases/footnote_in_inline.xml?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/hyphenation-testcases/footnote_in_inline.xml (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/hyphenation-testcases/footnote_in_inline.xml Tue Sep 25 01:41:51 2007
@@ -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>

Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/standard-testcases/inline-level_id.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/standard-testcases/inline-level_id.xml?rev=579125&r1=579124&r2=579125&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/standard-testcases/inline-level_id.xml (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/test/layoutengine/standard-testcases/inline-level_id.xml Tue Sep 25 01:41:51 2007
@@ -65,7 +65,7 @@
   </fo>
   <checks>
     <eval expected="inline1" xpath="//pageViewport[@nr=1]/page/regionViewport/regionBody/mainReference/span/flow/block[1]/lineArea/inlineparent/@prod-id"/>
-    <!-- wrapper skipped -->
+    <eval expected="wrapper1" xpath="//pageViewport[@nr=1]/page/regionViewport/regionBody/mainReference/span/flow/block[2]/lineArea/inline/@prod-id"/>
     <!--eval expected="inline-container1" xpath="//pageViewport[@nr=1]/page/regionViewport/regionBody/mainReference/span/flow/block[3]/lineArea/???/@prod-id"/-->
     <eval expected="page-number1" xpath="//pageViewport[@nr=1]/page/regionViewport/regionBody/mainReference/span/flow/block[4]/lineArea/text[2]/@prod-id"/>
     <eval expected="page-number-citation1" xpath="//pageViewport[@nr=1]/page/regionViewport/regionBody/mainReference/span/flow/block[5]/lineArea/text[2]/@prod-id"/>



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org