]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Fixed an off by one error in the end of stream encoding part of ASCII85Filter
authorKelly Campbell <kellyc@apache.org>
Thu, 1 Feb 2001 09:08:08 +0000 (09:08 +0000)
committerKelly Campbell <kellyc@apache.org>
Thu, 1 Feb 2001 09:08:08 +0000 (09:08 +0000)
as reported by Alex Cherepanov.

Cleaned up the code a bit and added some better comments too.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194006 13f79535-47bb-0310-9956-ffa450edef68

src/org/apache/fop/pdf/ASCII85Filter.java

index 13368c4eed3dd0496eeda61cf021fab02f0070ec..7ef711c4520901f48feef518e795e2b75f6a15dd 100644 (file)
@@ -79,105 +79,132 @@ public class ASCII85Filter extends PDFFilter
     public byte[] encode(byte[] data) 
     {
        
-       StringBuffer buffer = new StringBuffer();
+       ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+       
        int i;
        int total = 0;
        int diff = 0;
        
+       // first encode the majority of the data
+       // each 4 byte group becomes a 5 byte group
        for (i = 0; i+3 < data.length; i+=4) {
-           byte b1 = data[i];
-           byte b2 = data[i+1];
-           byte b3 = data[i+2];
-           byte b4 = data[i+3];
-           
-           long val = ((b1 << 24) & 0xff000000L) 
-               + ((b2 << 16) & 0xff0000L) 
-               + ((b3 << 8) & 0xff00L) 
-               + (b4 & 0xffL);
-           String conv = convertLong(val);
            
-           buffer.append(conv);
-
+           long val = ((data[i] << 24) & 0xff000000L) // note: must have the L at the 
+               + ((data[i+1] << 16) & 0xff0000L)     // end, otherwise you get into
+               + ((data[i+2] << 8) & 0xff00L)        // weird signed value problems
+               + (data[i+3] & 0xffL);                // cause we're using a full 32 bits
+           byte[] conv = convertWord(val);
+                   
+           buffer.write(conv,0,conv.length);
            
        }
 
-       
+       // now take care of the trailing few bytes.
+       // with n leftover bytes, we append 0 bytes to make a full group of 4
+        // then convert like normal (except not applying the special zero rule)
+       // and write out the first n+1 bytes from the result
        if (i < data.length) {
            int n = data.length - i;
-           byte b1,b2,b3,b4;
-           b1 = data[i++];
-           if (i < data.length) {
-               b2 = data[i++];
-           }
-           else {
-               b2 = 0;
-           }
-           if (i < data.length) {
-               b3 = data[i++];
-           }
-           else {
-               b3 = 0;
+           byte[] lastdata = new byte[4];
+           for (int j=0; j<4; j++) {
+               if (j<n) {
+                   lastdata[j] = data[i++];
+               }
+               else {
+                   lastdata[j] = 0;
+               }
            }
-           // assert i = data.length
-           b4 = 0;
           
-           long val = ((b1 << 24) & 0xff000000L) 
-               + ((b2 << 16) & 0xff0000L) 
-               + ((b3 << 8) & 0xff00L) 
-               + (b4 & 0xffL);
-           String converted = convertLong(val);
+           long val = ((lastdata[0] << 24) & 0xff000000L) 
+               + ((lastdata[1] << 16) & 0xff0000L) 
+               + ((lastdata[2] << 8) & 0xff00L) 
+               + (lastdata[3] & 0xffL);
+           byte[] conv= convertWord(val);
            
            // special rule for handling zeros at the end
            if (val == 0) {
-               converted = "!!!!!";
+               conv = new byte[5];
+               for (int j=0;j<5;j++) {
+                   conv[j] = (byte)'!';
+               }
            }
-           buffer.append(converted.substring(0,n));
+           // assert n+1 <= 5
+           buffer.write(conv,0,n+1);
+           //    System.out.println("ASCII85 end of data was "+n+" bytes long");
+           
        }
-       buffer.append(ASCII85_EOD);
-       return buffer.toString().getBytes();
+       // finally write the two character end of data marker
+       buffer.write(ASCII85_EOD.getBytes(),0,ASCII85_EOD.getBytes().length);
+               
+
+       byte[] result = buffer.toByteArray();
+       
+
+       // assert that we have the correct outgoing length
+       /*
+       int in = (data.length % 4);
+       int out = (result.length-ASCII85_EOD.getBytes().length) % 5;
+
+       if ((in+1 != out) && !(in == 0 && out == 0)) {
+           System.out.println("ASCII85 assertion failed:");
+           System.out.println("        inlength = "+data.length+" inlength % 4 = "+(data.length % 4)+" outlength = "+(result.length-ASCII85_EOD.getBytes().length)+" outlength % 5 = "+((result.length-ASCII85_EOD.getBytes().length) % 5));
+       }
+       */      
+       return result;
        
     }
     
-    private String convertLong(long val) 
+    /**
+     * This converts a 32 bit value (4 bytes) into 5 bytes using base 85.
+     * each byte in the result starts with zero at the '!' character so
+     * the resulting base85 number fits into printable ascii chars
+     *
+     * @param word the 32 bit unsigned (hence the long datatype) word
+     * @return 5 bytes (or a single byte of the 'z' character for word
+     * values of 0) 
+     */
+    private byte[] convertWord(long word) 
     {
-       val = val & 0xffffffff;
-       if (val < 0) {
-           val = -val;
+       word = word & 0xffffffff;
+       if (word < 0) {
+           word = -word;
        }
        
-       if (val == 0) {
-           return new Character(ASCII85_ZERO).toString();
+       if (word == 0) {
+           byte[] result = { (byte)ASCII85_ZERO };
+           return result;
        }
        else {
-           byte c1 = (byte)((val / base85_1) & 0xFF);
-           byte c2 = (byte)(((val - (c1 * base85_1)) / base85_2) & 0xFF);
-           byte c3 = (byte)(((val 
+           byte c1 = (byte)((word / base85_1) & 0xFF);
+           byte c2 = (byte)(((word - (c1 * base85_1)) / base85_2) & 0xFF);
+           byte c3 = (byte)(((word 
                       - (c1 * base85_1) 
                       - (c2 * base85_2) 
                       ) / base85_3) & 0xFF);
-           byte c4 = (byte)(((val 
+           byte c4 = (byte)(((word 
                       - (c1 * base85_1) 
                       - (c2 * base85_2)
                       - (c3 * base85_3)
                       ) / base85_4) & 0xFF);
-           byte c5 = (byte)(((val 
+           byte c5 = (byte)(((word 
                       - (c1 * base85_1) 
                       - (c2 * base85_2)
                       - (c3 * base85_3)
                       - (c4 * base85_4))) & 0xFF);
                        
-           char[] ret = {(char)(c1+ASCII85_START),
-                          (char)(c2+ASCII85_START),
-                          (char)(c3+ASCII85_START),
-                          (char)(c4+ASCII85_START),
-                          (char)(c5+ASCII85_START)};
+           byte[] ret = {(byte)(c1+ASCII85_START),
+                         (byte)(c2+ASCII85_START),
+                         (byte)(c3+ASCII85_START),
+                         (byte)(c4+ASCII85_START),
+                         (byte)(c5+ASCII85_START)};
            for (int i = 0; i< ret.length; i++) {
                if (ret[i] < 33 || ret[i] > 117) {
                    System.out.println("illegal char value "+new Integer(ret[i]));
                }
            }
+
+           return ret;
            
-           return new String(ret);
                    
        }       
     }