Author: vhennebert
Date: Mon Mar 19 15:56:19 2012
New Revision: 1302518

URL: http://svn.apache.org/viewvc?rev=1302518&view=rev
Log:
Bugzilla #51385: Added configuration option to set the version of the output 
PDF document.

Patch by Mehdi Houshmand, applied with minor modifications

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java   (with 
props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java   
(with props)
    
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java
   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java   
(with props)
Modified:
    
xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFInfo.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java
    
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java
    
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
    
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
    xmlgraphics/fop/trunk/status.xml

Modified: 
xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- 
xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml 
(original)
+++ 
xmlgraphics/fop/trunk/src/documentation/content/xdocs/trunk/configuration.xml 
Mon Mar 19 15:56:19 2012
@@ -395,6 +395,18 @@
          <noprinthq/>
       </encryption-params>
     </renderer>]]></source>
+     <p>
+       By default FOP produces PDF files of version 1.4, but this can be 
changed in order to benefit 
+       from features that appeared in newer versions of PDF. At the moment, 
only a few features from 
+       PDF 1.5 have been implemented, but the configuration element will 
accept any value between 
+       1.4 and 1.7. This is the value that will appear in the PDF header, 
although only features up 
+       to 1.5 will actually be used.
+      <source><![CDATA[
+      <renderer mime="application/pdf">
+        <version>1.5</version>
+        <!-- Versions 1.4, 1.5, 1.6 and 1.7 are accepted, all other values are 
invalid -->
+      </renderer>]]></source>
+     </p>
       
     </section>
     <section id="ps-renderer">
@@ -522,4 +534,4 @@ information it finds. Check if FOP finds
 
         </section>
   </body>
-</document>
\ No newline at end of file
+</document>

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java 
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java Mon Mar 
19 15:56:19 2012
@@ -65,12 +65,6 @@ public class PDFDocument {
 
     private static final Long LOCATION_PLACEHOLDER = new Long(0);
 
-    /** Integer constant to represent PDF 1.3 */
-    public static final int PDF_VERSION_1_3 = 3;
-
-    /** Integer constant to represent PDF 1.4 */
-    public static final int PDF_VERSION_1_4 = 4;
-
     /** the encoding to use when converting strings to PDF commands */
     public static final String ENCODING = "ISO-8859-1";
 
@@ -95,8 +89,8 @@ public class PDFDocument {
     /** the objects themselves */
     private List objects = new LinkedList();
 
-    /** Indicates what PDF version is active */
-    private int pdfVersion = PDF_VERSION_1_4;
+    /** Controls the PDF version of this document */
+    private VersionController versionController;
 
     /** Indicates which PDF profiles are active (PDF/A, PDF/X etc.) */
     private PDFProfile pdfProfile = new PDFProfile(this);
@@ -197,6 +191,24 @@ public class PDFDocument {
      * @param prod the name of the producer of this pdf document
      */
     public PDFDocument(String prod) {
+        this(prod, null);
+        versionController = 
VersionController.getDynamicVersionController(Version.V1_4, this);
+    }
+
+    /**
+     * Creates an empty PDF document.
+     *
+     * The constructor creates a /Root and /Pages object to
+     * track the document but does not write these objects until
+     * the trailer is written. Note that the object ID of the
+     * pages object is determined now, and the xref table is
+     * updated later. This allows Pages to refer to their
+     * Parent before we write it out.
+     *
+     * @param prod the name of the producer of this pdf document
+     * @param versionController the version controller of this PDF document
+     */
+    public PDFDocument(String prod, VersionController versionController) {
 
         this.factory = new PDFFactory(this);
 
@@ -211,26 +223,32 @@ public class PDFDocument {
 
         // Make the /Info record
         this.info = getFactory().makeInfo(prod);
+
+        this.versionController = versionController;
+    }
+
+    /**
+     * Returns the current PDF version.
+     *
+     * @return returns the PDF version
+     */
+    public Version getPDFVersion() {
+        return versionController.getPDFVersion();
     }
 
     /**
-     * @return the integer representing the active PDF version
-     *          (one of PDFDocument.PDF_VERSION_*)
+     * Sets the PDF version of this document.
+     *
+     * @param version the PDF version
+     * @throws IllegalStateException if the version of this PDF is not allowed 
to change.
      */
-    public int getPDFVersion() {
-        return this.pdfVersion;
+    public void setPDFVersion(Version version) {
+        versionController.setPDFVersion(version);
     }
 
-    /** @return the String representing the active PDF version */
+    /** @return the String representing the current PDF version */
     public String getPDFVersionString() {
-        switch (getPDFVersion()) {
-        case PDF_VERSION_1_3:
-            return "1.3";
-        case PDF_VERSION_1_4:
-            return "1.4";
-        default:
-            throw new IllegalStateException("Unsupported PDF version 
selected");
-        }
+        return versionController.getPDFVersion().toString();
     }
 
     /** @return the PDF profile currently active. */

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java 
(original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFile.java Mon 
Mar 19 15:56:19 2012
@@ -34,7 +34,7 @@ public class PDFEmbeddedFile extends PDF
         super();
         put("Type", new PDFName("EmbeddedFile"));
         PDFDictionary params = new PDFDictionary();
-        params.put("CreationDate", params.formatDateTime(new Date()));
+        params.put("CreationDate", PDFInfo.formatDateTime(new Date()));
         put("Params", params);
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFInfo.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFInfo.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFInfo.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFInfo.java Mon Mar 19 
15:56:19 2012
@@ -21,7 +21,11 @@ package org.apache.fop.pdf;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
 import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
 
 /**
  * class representing an /Info object
@@ -232,5 +236,67 @@ public class PDFInfo extends PDFObject {
         return bout.toByteArray();
     }
 
+    /**
+     * Returns a SimpleDateFormat instance for formatting PDF date-times.
+     * @return a new SimpleDateFormat instance
+     */
+    protected static SimpleDateFormat getPDFDateFormat() {
+        SimpleDateFormat df = new SimpleDateFormat("'D:'yyyyMMddHHmmss", 
Locale.ENGLISH);
+        df.setTimeZone(TimeZone.getTimeZone("GMT"));
+        return df;
+    }
+
+    /**
+     * Formats a date/time according to the PDF specification 
(D:YYYYMMDDHHmmSSOHH'mm').
+     * @param time date/time value to format
+     * @param tz the time zone
+     * @return the requested String representation
+     */
+    protected static String formatDateTime(Date time, TimeZone tz) {
+        Calendar cal = Calendar.getInstance(tz, Locale.ENGLISH);
+        cal.setTime(time);
+
+        int offset = cal.get(Calendar.ZONE_OFFSET);
+        offset += cal.get(Calendar.DST_OFFSET);
+
+        // DateFormat is operating on GMT so adjust for time zone offset
+        Date dt1 = new Date(time.getTime() + offset);
+        StringBuffer sb = new StringBuffer();
+        sb.append(getPDFDateFormat().format(dt1));
+
+        offset /= (1000 * 60); // Convert to minutes
+
+        if (offset == 0) {
+            sb.append('Z');
+        } else {
+            if (offset > 0) {
+                sb.append('+');
+            } else {
+                sb.append('-');
+            }
+            int offsetHour = Math.abs(offset / 60);
+            int offsetMinutes = Math.abs(offset % 60);
+            if (offsetHour < 10) {
+                sb.append('0');
+            }
+            sb.append(Integer.toString(offsetHour));
+            sb.append('\'');
+            if (offsetMinutes < 10) {
+                sb.append('0');
+            }
+            sb.append(Integer.toString(offsetMinutes));
+            sb.append('\'');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Formats a date/time according to the PDF specification. 
(D:YYYYMMDDHHmmSSOHH'mm').
+     * @param time date/time value to format
+     * @return the requested String representation
+     */
+    protected static String formatDateTime(Date time) {
+        return formatDateTime(time, TimeZone.getDefault());
+    }
 }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java Mon Mar 19 
15:56:19 2012
@@ -23,11 +23,6 @@ package org.apache.fop.pdf;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -340,71 +335,6 @@ public abstract class PDFObject implemen
     }
 
     /**
-     * Returns a SimpleDateFormat instance for formatting PDF date-times.
-     * @return a new SimpleDateFormat instance
-     */
-    protected SimpleDateFormat getPDFDateFormat() {
-        SimpleDateFormat df = new SimpleDateFormat("'D:'yyyyMMddHHmmss", 
Locale.ENGLISH);
-        df.setTimeZone(TimeZone.getTimeZone("GMT"));
-        return df;
-    }
-
-    /**
-     * Formats a date/time according to the PDF specification
-     * (D:YYYYMMDDHHmmSSOHH'mm').
-     * @param time date/time value to format
-     * @param tz the time zone
-     * @return the requested String representation
-     */
-    protected String formatDateTime(Date time, TimeZone tz) {
-        Calendar cal = Calendar.getInstance(tz, Locale.ENGLISH);
-        cal.setTime(time);
-
-        int offset = cal.get(Calendar.ZONE_OFFSET);
-        offset += cal.get(Calendar.DST_OFFSET);
-
-        //DateFormat is operating on GMT so adjust for time zone offset
-        Date dt1 = new Date(time.getTime() + offset);
-        StringBuffer sb = new StringBuffer();
-        sb.append(getPDFDateFormat().format(dt1));
-
-        offset /= (1000 * 60); //Convert to minutes
-
-        if (offset == 0) {
-            sb.append('Z');
-        } else {
-            if (offset > 0) {
-                sb.append('+');
-            } else {
-                sb.append('-');
-            }
-            int offsetHour = Math.abs(offset / 60);
-            int offsetMinutes = Math.abs(offset % 60);
-            if (offsetHour < 10) {
-                sb.append('0');
-            }
-            sb.append(Integer.toString(offsetHour));
-            sb.append('\'');
-            if (offsetMinutes < 10) {
-                sb.append('0');
-            }
-            sb.append(Integer.toString(offsetMinutes));
-            sb.append('\'');
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Formats a date/time according to the PDF specification.
-     * (D:YYYYMMDDHHmmSSOHH'mm').
-     * @param time date/time value to format
-     * @return the requested String representation
-     */
-    protected String formatDateTime(Date time) {
-        return formatDateTime(time, TimeZone.getDefault());
-    }
-
-    /**
      * Check if the other PDFObject has the same content as the current object.
      * <p>
      * Note: This function has a contract which is less binding than

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java Mon Mar 
19 15:56:19 2012
@@ -184,11 +184,11 @@ public class PDFProfile {
     public void verifyPDFVersion() {
         final String err = "PDF version must be 1.4 for {0}";
         if (getPDFAMode().isPDFA1LevelB()
-                && getDocument().getPDFVersion() != 
PDFDocument.PDF_VERSION_1_4) {
+                && !Version.V1_4.equals(getDocument().getPDFVersion())) {
             throw new PDFConformanceException(format(err, getPDFAMode()));
         }
         if (getPDFXMode() == PDFXMode.PDFX_3_2003
-                && getDocument().getPDFVersion() != 
PDFDocument.PDF_VERSION_1_4) {
+                && !Version.V1_4.equals(getDocument().getPDFVersion())) {
             throw new PDFConformanceException(format(err, getPDFXMode()));
         }
     }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java Mon Mar 19 
15:56:19 2012
@@ -205,7 +205,7 @@ public class PDFRoot extends PDFDictiona
      * @since PDF 1.4
      */
     public void setMetadata(PDFMetadata meta) {
-        if (getDocumentSafely().getPDFVersion() >= 
PDFDocument.PDF_VERSION_1_4) {
+        if (getDocumentSafely().getPDFVersion().compareTo(Version.V1_4) >= 0) {
             put("Metadata", meta.makeReference());
         }
     }
@@ -235,7 +235,7 @@ public class PDFRoot extends PDFDictiona
      * @since PDF 1.4
      */
     public void addOutputIntent(PDFOutputIntent outputIntent) {
-        if (getDocumentSafely().getPDFVersion() >= 
PDFDocument.PDF_VERSION_1_4) {
+        if (getDocumentSafely().getPDFVersion().compareTo(Version.V1_4) >= 0) {
             PDFArray outputIntents = getOutputIntents();
             if (outputIntents == null) {
                 outputIntents = new PDFArray(this);
@@ -246,6 +246,17 @@ public class PDFRoot extends PDFDictiona
     }
 
     /**
+     * Sets the "Version" entry. If this version is greater than that 
specified in the header, this
+     * version takes precedence.
+     *
+     * @param version the PDF document version
+     * @since PDF 1.4
+     */
+    void setVersion(Version version) {
+        put("Version", new PDFName(version.toString()));
+    }
+
+    /**
      * Returns the language identifier of the document.
      * @return the language identifier of the document (or null if not set or 
undefined)
      * @since PDF 1.4

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java?rev=1302518&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java Mon Mar 19 
15:56:19 2012
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+/**
+ * A version of PDF. Values are ordered such that compareTo() gives sensible
+ * results (e.g., {@code V1_4.compareTo(V1_5) < 0}).
+ */
+public enum Version {
+    /** PDF v1 */
+    V1_0("1.0"),
+    /** PDF v1.1 */
+    V1_1("1.1"),
+    /** PDF v1.2 */
+    V1_2("1.2"),
+    /** PDF v1.3 */
+    V1_3("1.3"),
+    /** PDF v1.4 */
+    V1_4("1.4"),
+    /** PDF v1.5 */
+    V1_5("1.5"),
+    /** PDF v1.6 */
+    V1_6("1.6"),
+    /** PDF v1.7 */
+    V1_7("1.7");
+
+    private String version;
+
+    private Version(String version) {
+        this.version = version;
+    }
+
+    /**
+     * Given the PDF version as a String, returns the corresponding enumerated 
type. The String
+     * should be in the format "1.x" for PDF v1.x.
+     *
+     * @param version a version number
+     * @return the corresponding Version instance
+     * @throws IllegalArgumentException if the argument does not correspond to 
any existing PDF version
+     */
+    public static Version getValueOf(String version) {
+        for (Version pdfVersion : Version.values()) {
+            if (pdfVersion.toString().equals(version)) {
+                return pdfVersion;
+            }
+        }
+        throw new IllegalArgumentException("Invalid PDF version given: " + 
version);
+    }
+
+    @Override
+    public String toString() {
+        return version;
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/Version.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java?rev=1302518&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java 
(added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java 
Mon Mar 19 15:56:19 2012
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+/**
+ * An abstraction that controls the mutability of the PDF version for a 
document.
+ */
+public abstract class VersionController {
+
+    private Version version;
+
+    private VersionController(Version version) {
+        this.version = version;
+    }
+
+    /**
+     * Returns the PDF version of the document.
+     *
+     * @return the PDF version
+     */
+    public Version getPDFVersion() {
+        return version;
+    }
+
+    /**
+     * Sets the PDF version of the document.
+     *
+     * @param version the PDF version
+     * @throws IllegalStateException if the PDF version is not allowed to 
change.
+     */
+    public abstract void setPDFVersion(Version version);
+
+    @Override
+    public String toString() {
+        return version.toString();
+    }
+
+    /**
+     * A class representing the version of a PDF document. This class doesn't 
allow the version to
+     * change once it has been set, it is immutable. Any attempt to set the 
version will result in
+     * an exception being thrown.
+     */
+    private static final class FixedVersion extends VersionController {
+
+        private FixedVersion(Version version) {
+            super(version);
+        }
+
+        @Override
+        public void setPDFVersion(Version version) {
+            throw new IllegalStateException("Cannot change the version of this 
PDF document.");
+        }
+    }
+
+    /**
+     * A class representing the version of a PDF document. This class allows 
the version to be
+     * changed once it has been set (it is mutable) ONLY if the new version is 
greater. If the PDF
+     * version is changed after it has been instantiated, the version will be 
set in the document
+     * catalog.
+     */
+    private static final class DynamicVersion extends VersionController {
+
+        private PDFDocument doc;
+
+        private DynamicVersion(Version version, PDFDocument doc) {
+            super(version);
+            this.doc = doc;
+        }
+
+        @Override
+        public void setPDFVersion(Version version) {
+            if (super.version.compareTo(version) < 0) {
+                super.version = version;
+                doc.getRoot().setVersion(version);
+            }
+        }
+    }
+
+    /**
+     * Returns a controller that disallows subsequent change to the document's 
version. The minimum
+     * allowed version is v1.4.
+     *
+     * @param version the PDF version (must be &gt;= v1.4)
+     * @return the fixed PDF version controller
+     */
+    public static VersionController getFixedVersionController(Version version) 
{
+        if (version.compareTo(Version.V1_4) < 0) {
+            throw new IllegalArgumentException("The PDF version cannot be set 
below version 1.4");
+        }
+        return new FixedVersion(version);
+    }
+
+    /**
+     * Returns a controller that allows subsequent changes to the document's 
version.
+     *
+     * @param initialVersion the initial PDF version
+     * @param doc the document whose version is being set
+     * @return the dynamic PDF version controller
+     */
+    public static VersionController getDynamicVersionController(Version 
initialVersion,
+            PDFDocument doc) {
+        return new DynamicVersion(initialVersion, doc);
+    }
+}

Propchange: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/VersionController.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Modified: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java
 (original)
+++ 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFConfigurationConstants.java
 Mon Mar 19 15:56:19 2012
@@ -74,6 +74,8 @@ public interface PDFConfigurationConstan
     String PDF_X_MODE = "pdf-x-mode";
     /** Rendering Options key for the ICC profile for the output intent. */
     String KEY_OUTPUT_PROFILE = "output-profile";
+    /** PDF version entry: specify the version of the PDF document created, 
datatype: String */
+    String PDF_VERSION = "version";
     /**
      * Rendering Options key for disabling the sRGB color space (only possible 
if no PDF/A or
      * PDF/X profile is active).

Modified: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
 (original)
+++ 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
 Mon Mar 19 15:56:19 2012
@@ -157,6 +157,8 @@ public class PDFRendererConfigurator ext
             pdfUtil.setDisableSRGBColorSpace(
                     disableColorSpaceConfig.getValueAsBoolean(false));
         }
+
+        setPDFDocVersion(cfg, pdfUtil);
     }
 
     private int checkEncryptionLength(int encryptionLength) {
@@ -175,6 +177,22 @@ public class PDFRendererConfigurator ext
         return correctEncryptionLength;
     }
 
+    private void setPDFDocVersion(Configuration cfg, PDFRenderingUtil pdfUtil) 
throws FOPException {
+        Configuration pdfVersion = 
cfg.getChild(PDFConfigurationConstants.PDF_VERSION, false);
+        if (pdfVersion != null) {
+            String version = pdfVersion.getValue(null);
+            if (version != null && version.length() != 0) {
+                try {
+                    pdfUtil.setPDFVersion(version);
+                } catch (IllegalArgumentException e) {
+                    throw new FOPException(e.getMessage());
+                }
+            } else {
+                throw new FOPException("The PDF version has not been set.");
+            }
+        }
+    }
+
     /**
      * Builds a filter map from an Avalon Configuration object.
      *

Modified: 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java 
(original)
+++ 
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java 
Mon Mar 19 15:56:19 2012
@@ -64,6 +64,8 @@ import org.apache.fop.pdf.PDFPageLabels;
 import org.apache.fop.pdf.PDFReference;
 import org.apache.fop.pdf.PDFText;
 import org.apache.fop.pdf.PDFXMode;
+import org.apache.fop.pdf.Version;
+import org.apache.fop.pdf.VersionController;
 import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileExtensionAttachment;
 
 /**
@@ -102,6 +104,8 @@ class PDFRenderingUtil implements PDFCon
     /** Optional URI to an output profile to be used. */
     protected String outputProfileURI;
 
+    protected Version maxPDFVersion;
+
 
     PDFRenderingUtil(FOUserAgent userAgent) {
         this.userAgent = userAgent;
@@ -375,8 +379,16 @@ class PDFRenderingUtil implements PDFCon
         if (this.pdfDoc != null) {
             throw new IllegalStateException("PDFDocument already set up");
         }
-        this.pdfDoc = new PDFDocument(
-                userAgent.getProducer() != null ? userAgent.getProducer() : 
"");
+
+        String producer = userAgent.getProducer() != null ? 
userAgent.getProducer() : "";
+
+        if (maxPDFVersion == null) {
+            this.pdfDoc = new PDFDocument(producer);
+        } else {
+            VersionController controller =
+                    VersionController.getFixedVersionController(maxPDFVersion);
+            this.pdfDoc = new PDFDocument(producer, controller);
+        }
         updateInfo();
         updatePDFProfiles();
         pdfDoc.setFilterMap(filterMap);
@@ -482,4 +494,14 @@ class PDFRenderingUtil implements PDFCon
         nameArray.add(new PDFReference(fileSpec));
     }
 
+    /**
+     * Sets the PDF version of the output document. See {@link Version} for 
the format of
+     * <code>version</code>.
+     * @param version the PDF version
+     * @throws IllegalArgumentException if the format of version doesn't 
conform to that specified
+     * by {@link Version}
+     */
+    public void setPDFVersion(String version) {
+        maxPDFVersion = Version.getValueOf(version);
+    }
 }

Modified: xmlgraphics/fop/trunk/status.xml
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=1302518&r1=1302517&r2=1302518&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Mon Mar 19 15:56:19 2012
@@ -62,6 +62,9 @@
       documents. Example: the fix of marks layering will be such a case when 
it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Code" dev="VH" type="add" fixes-bug="51385" 
due-to="Mehdi Houshmand">
+        Added configuration option to set the version of the output PDF 
document.
+      </action>
       <action context="Code" dev="MH" type="fix" fixes-bug="52849" 
due-to="Luis Bernardo">
         Fixed bug that caused a configured and installed SVG font to stroked,
         also added an event indicating when fonts are stroked.

Added: 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java?rev=1302518&view=auto
==============================================================================
--- 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java
 (added)
+++ 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java
 Mon Mar 19 15:56:19 2012
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * A test class for {@link VersionController}.
+ */
+public class VersionControllerTestCase {
+
+    private PDFDocument doc;
+
+    @Before
+    public void setUp() {
+        doc = new PDFDocument("test");
+    }
+
+    @Test
+    public void testGetVersion() {
+        // These do the same thing
+        for (Version version : Version.values()) {
+            if (version.compareTo(Version.V1_4) >= 0) {
+                VersionController fixedVC = 
VersionController.getFixedVersionController(version);
+                assertEquals(version, fixedVC.getPDFVersion());
+            }
+
+            VersionController dynamicVC = 
VersionController.getDynamicVersionController(version,
+                    doc);
+            assertEquals(version, dynamicVC.getPDFVersion());
+        }
+    }
+
+    /**
+     * Tests that the setter methods work at setting the underlying version.
+     * Here there is a disparity between the two objects, the fixed version 
will
+     * throw an exception if the setter is invoked. The dynamic version will
+     * allow the version to be changed, if the new version is greater than the
+     * version already set.
+     */
+    @Test
+    public void testSetVersion() {
+        // Create every type of expected PDFVersion
+        for (Version originalVersion : Version.values()) {
+            // Compare against every type of Version
+            for (Version setVersion : Version.values()) {
+                testDynamicController(originalVersion, setVersion);
+                testFixedController(originalVersion, setVersion);
+            }
+
+        }
+    }
+
+    /**
+     * The fixed implementation will throw an exception if an attempt is made 
to change its
+     * version.
+     *
+     * @param originalVersion the version given to the constructor when 
PDFVersion instantiated
+     * @param setVersion the version being set
+     */
+    private void testFixedController(Version originalVersion, Version 
setVersion) {
+        if (originalVersion.compareTo(Version.V1_4) >= 0) {
+            VersionController fixedVC = VersionController
+                    .getFixedVersionController(originalVersion);
+            try {
+                fixedVC.setPDFVersion(setVersion);
+                fail("The FixedVersionController should throw an exception if 
an attempt to change "
+                        + "the version is made");
+            } catch (IllegalStateException e) {
+                // PASS
+            }
+            // Changes are NOT allowed, the original version is immutable
+            assertEquals(originalVersion, fixedVC.getPDFVersion());
+            // The document version is NEVER changed
+            assertEquals(Version.V1_4, doc.getPDFVersion());
+            // the /Version parameter shouldn't be present in the document 
catalog
+            assertNull(doc.getRoot().get("Version"));
+        } else {
+            try {
+                VersionController.getFixedVersionController(originalVersion);
+                fail("Versions < 1.4 aren't allowed.");
+            } catch (IllegalArgumentException e) {
+                // PASS
+            }
+        }
+    }
+
+    /**
+     * The dynamic implementation allows the version to be changed. However, 
the version given in
+     * the constructor will be the version set in the header of the PDF 
document. Any change to the
+     * version will then be made in the document catalog.
+     *
+     * @param originalVersion the version given to the constructor when 
PDFVersion instantiated
+     * @param setVersion the version being set
+     */
+    private void testDynamicController(Version originalVersion, Version 
setVersion) {
+        VersionController testSubj = 
VersionController.getDynamicVersionController(originalVersion,
+                doc);
+        testSubj.setPDFVersion(setVersion);
+        PDFName nameVersion = new PDFName(setVersion.toString());
+
+        if (originalVersion.compareTo(setVersion) < 0) {
+            versionShouldChange(setVersion, testSubj, nameVersion);
+        } else {
+            versionShouldNotChange(originalVersion, testSubj);
+        }
+        doc.getRoot().put("Version", null);
+    }
+
+    private void versionShouldNotChange(Version originalVersion, 
VersionController testSubj) {
+        assertEquals(originalVersion, testSubj.getPDFVersion());
+        assertNull(doc.getRoot().get("Version"));
+    }
+
+    private void versionShouldChange(Version setVersion, VersionController 
testSubj,
+            PDFName nameVersion) {
+        assertEquals(setVersion, testSubj.getPDFVersion());
+        assertEquals(nameVersion.toString(), 
doc.getRoot().get("Version").toString());
+    }
+}

Propchange: 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionControllerTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java?rev=1302518&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java 
(added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java Mon 
Mar 19 15:56:19 2012
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * This is a test case for ({@link Version}.
+ */
+public class VersionTestCase {
+
+    /**
+     * Test the <code>getValue()</code> method. This should return {@link 
Version} given a
+     * {@link String}.
+     */
+    @Test
+    public void testGetValue() {
+        int index = 0;
+        for (Version version : Version.values()) {
+            assertEquals(version, Version.getValueOf("1." + index++));
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetValueIllegalArgument() {
+        Version.getValueOf("blah");
+    }
+
+    /**
+     * Tests that the <code>toString()</method> method returns the PDF version 
string of the proper
+     * format.
+     */
+    @Test
+    public void testToString() {
+        // Test all the normal values
+        int index = 0;
+        for (Version version : Version.values()) {
+            assertTrue(version.toString().equals("1." + index++));
+        }
+    }
+
+    /**
+     * Tests that the <code>compareTo()</code> contract is obeyed.
+     */
+    @Test
+    public void testCompareTo() {
+        // Ensure that the implicit comparison contract is satisfied
+        Version[] expected = {
+                Version.V1_0,
+                Version.V1_1,
+                Version.V1_2,
+                Version.V1_3,
+                Version.V1_4,
+                Version.V1_5,
+                Version.V1_6,
+                Version.V1_7
+        };
+
+        Version[] actual = Version.values();
+
+        for (int i = 0; i < actual.length - 1; i++) {
+            assertEquals(-1, actual[i].compareTo(expected[i + 1]));
+
+            assertEquals(0, actual[i].compareTo(expected[i]));
+
+            assertEquals(1, actual[i + 1].compareTo(expected[i]));
+        }
+    }
+}

Propchange: 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/VersionTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Revision Id



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to