Fixed merge problems.
Fixed a NPE when a mask is null in BitmapImage.java
Add support for properly encoding binary data as a hexadecimal string object (including encryption).
Adjust palette generation for indexed bitmaps to work correctly with encryption.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign@611133 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/java/org/apache/fop/pdf/BitmapImage.java b/src/java/org/apache/fop/pdf/BitmapImage.java
index b488d78..69b51da 100644
--- a/src/java/org/apache/fop/pdf/BitmapImage.java
+++ b/src/java/org/apache/fop/pdf/BitmapImage.java
@@ -56,7 +56,9 @@
         this.bitsPerComponent = 8;
         this.colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
         this.bitmaps = data;
-        maskRef = new PDFReference(mask);
+        if (mask != null) {
+            maskRef = new PDFReference(mask);
+        }
     }
 
     /**
diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java
index f531835..4bfd805 100644
--- a/src/java/org/apache/fop/pdf/PDFObject.java
+++ b/src/java/org/apache/fop/pdf/PDFObject.java
@@ -276,14 +276,23 @@
      */
     protected byte[] encodeString(String string) {
         return encodeText(string);
-        /*
-        final byte[] buf = encode(PDFText.escapeString(string));
+    }
+    
+    /**
+     * Encodes binary data as hexadecimal string object.
+     * @param data the binary data
+     * @param out the OutputStream to write the encoded object to
+     * @throws IOException if an I/O error occurs
+     */
+    protected void encodeBinaryToHexString(byte[] data, OutputStream out) throws IOException {
+        out.write('<');
         if (getDocumentSafely().isEncryptionActive()) {
-            return PDFText.escapeByteArray(
-                getDocument().getEncryption().encrypt(buf, this));
-        } else {
-            return buf;
-        }*/
+            data = getDocument().getEncryption().encrypt(data, this);
+        }
+        String hex = PDFText.toHex(data, false);
+        byte[] encoded = hex.getBytes("US-ASCII");
+        out.write(encoded);
+        out.write('>');
     }
     
     /**
@@ -307,6 +316,9 @@
             }
         } else if (obj instanceof Boolean) {
             writer.write(obj.toString());
+        } else if (obj instanceof byte[]) {
+            writer.flush();
+            encodeBinaryToHexString((byte[])obj, out);
         } else {
             writer.flush();
             out.write(encodeText(obj.toString()));
diff --git a/src/java/org/apache/fop/pdf/PDFReference.java b/src/java/org/apache/fop/pdf/PDFReference.java
index 3b61573..da388d3 100644
--- a/src/java/org/apache/fop/pdf/PDFReference.java
+++ b/src/java/org/apache/fop/pdf/PDFReference.java
@@ -51,6 +51,9 @@
      * @param ref an object reference
      */
     public PDFReference(String ref) {
+        if (ref == null) {
+            throw new NullPointerException("ref must not be null");
+        }
         this.indirectReference = ref;
     }
 
diff --git a/src/java/org/apache/fop/pdf/PDFText.java b/src/java/org/apache/fop/pdf/PDFText.java
index 4c17148..d380ac8 100644
--- a/src/java/org/apache/fop/pdf/PDFText.java
+++ b/src/java/org/apache/fop/pdf/PDFText.java
@@ -25,12 +25,12 @@
 
 /**
  * This class represents a simple number object. It also contains contains some 
- * utility methods for outputing numbers to PDF.
+ * utility methods for outputting numbers to PDF.
  */
 public class PDFText extends PDFObject {
 
-    private static final char[] DIGITS = 
-                                 {'0', '1', '2', '3', '4', '5', '6', '7',
+    private static final char[] DIGITS 
+                               = {'0', '1', '2', '3', '4', '5', '6', '7',
                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
                                   
     private String text;
@@ -145,20 +145,34 @@
     /**
      * Converts a byte array to a Hexadecimal String (3.2.3 in PDF 1.4 specs)
      * @param data the data to encode
+     * @param brackets true if enclosing brackets should be included
      * @return String the resulting string
      */
-    public static final String toHex(byte[] data) {
+    public static final String toHex(byte[] data, boolean brackets) {
         final StringBuffer sb = new StringBuffer(data.length * 2);
-        sb.append("<");
+        if (brackets) {
+            sb.append("<");
+        }
         for (int i = 0; i < data.length; i++) {
             sb.append(DIGITS[(data[i] >>> 4) & 0x0F]);
             sb.append(DIGITS[data[i] & 0x0F]);
         }
-        sb.append(">");
+        if (brackets) {
+            sb.append(">");
+        }
         return sb.toString();
     }
     
     /**
+     * Converts a byte array to a Hexadecimal String (3.2.3 in PDF 1.4 specs)
+     * @param data the data to encode
+     * @return String the resulting string
+     */
+    public static final String toHex(byte[] data) {
+        return toHex(data, true);
+    }
+    
+    /**
      * Converts a String to UTF-16 (big endian).
      * @param text text to convert
      * @return byte[] UTF-16 stream
diff --git a/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java
index ecf05db..62e83da 100644
--- a/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java
+++ b/src/java/org/apache/fop/render/pdf/ImageRenderedAdapter.java
@@ -25,6 +25,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 
+import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -41,7 +42,6 @@
 import org.apache.fop.pdf.PDFFilterList;
 import org.apache.fop.pdf.PDFName;
 import org.apache.fop.pdf.PDFReference;
-import org.apache.fop.pdf.PDFWritable;
 
 /**
  * PDFImage implementation for the PDF renderer which handles RenderedImages.
@@ -177,11 +177,6 @@
     }
 
     /** {@inheritDoc} */
-    public String getSoftMask() {
-        return softMask.toInlinePDFString();
-    }
-
-    /** {@inheritDoc} */
     public PDFReference getSoftMaskReference() {
         return softMask;
     }
@@ -203,7 +198,7 @@
         ColorModel cm = getEffectiveColorModel();
         if (cm instanceof IndexColorModel) {
             IndexColorModel icm = (IndexColorModel)cm;
-            PDFArray indexed = new PDFArray();
+            PDFArray indexed = new PDFArray(dict);
             indexed.add(new PDFName("Indexed"));
             
             if (icm.getColorSpace().getType() != ColorSpace.TYPE_RGB) {
@@ -219,30 +214,25 @@
                 throw new UnsupportedOperationException("hival must not go beyond " + MAX_HIVAL);
             }
             indexed.add(new Integer(hival));
-            final StringBuffer sb = new StringBuffer("<");
             int[] palette = new int[c];
             icm.getRGBs(palette);
+            ByteArrayOutputStream baout = new ByteArrayOutputStream();
             for (int i = 0; i < c; i++) {
-                if (i > 0) {
-                    sb.append(" ");
-                }
                 //TODO Probably doesn't work for non RGB based color spaces
-                rgb2Hex(palette[i], sb);
+                //See log warning above
+                int entry = palette[i];
+                baout.write((entry & 0xFF0000) >> 16);
+                baout.write((entry & 0xFF00) >> 8);
+                baout.write(entry & 0xFF);
             }
-            sb.append(">");
-            indexed.add(new PDFWritable() {
-                public String toInlinePDFString() {
-                    //Work-around String escaping. Maybe a little hacky.
-                    return sb.toString();
-                }
-            });
+            indexed.add(baout.toByteArray());
 
             dict.put("ColorSpace", indexed);
             dict.put("BitsPerComponent", icm.getPixelSize());
             
             Integer index = getIndexOfFirstTransparentColorInPalette(getImage().getRenderedImage());
             if (index != null) {
-                PDFArray mask = new PDFArray();
+                PDFArray mask = new PDFArray(dict);
                 mask.add(index);
                 mask.add(index);
                 dict.put("Mask", mask);
@@ -250,19 +240,6 @@
         }
     }
     
-    private static final char[] HEX = {
-        '0', '1', '2', '3', '4', '5', '6', '7',
-        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-    };
-
-    private static void rgb2Hex(int rgb, StringBuffer sb) {
-        for (int i = 5; i >= 0; i--) {
-            int shift = i * 4;
-            int n = (rgb & (15 << shift)) >> shift;
-            sb.append(HEX[n % 16]);
-        }
-    }
-    
     /** {@inheritDoc} */
     public String getFilterHint() {
         return PDFFilterList.IMAGE_FILTER;
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 95bab45..3b28cc3 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -39,11 +39,9 @@
 import javax.xml.transform.Source;
 import javax.xml.transform.stream.StreamSource;
 
-import org.w3c.dom.Document;
-
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.CountingOutputStream;
 
+import org.apache.xmlgraphics.image.loader.ImageException;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
 import org.apache.xmlgraphics.image.loader.ImageManager;
 import org.apache.xmlgraphics.image.loader.ImageSessionContext;
diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java
index 79d6893..21ae852 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -36,8 +36,6 @@
 
 import javax.xml.transform.Source;
 
-import org.w3c.dom.Document;
-
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -65,6 +63,8 @@
 import org.apache.xmlgraphics.ps.PSState;
 import org.apache.xmlgraphics.ps.dsc.DSCException;
 import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
+import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
+import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;
 
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;