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 ke...@apache.org on 2001/02/01 10:08:10 UTC

cvs commit: xml-fop/src/org/apache/fop/pdf ASCII85Filter.java

kellyc      01/02/01 01:08:09

  Modified:    src/org/apache/fop/pdf ASCII85Filter.java
  Log:
  Fixed an off by one error in the end of stream encoding part of ASCII85Filter
  as reported by Alex Cherepanov.
  
  Cleaned up the code a bit and added some better comments too.
  
  Revision  Changes    Path
  1.2       +83 -56    xml-fop/src/org/apache/fop/pdf/ASCII85Filter.java
  
  Index: ASCII85Filter.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/org/apache/fop/pdf/ASCII85Filter.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ASCII85Filter.java	2000/12/18 02:28:31	1.1
  +++ ASCII85Filter.java	2001/02/01 09:08:08	1.2
  @@ -1,4 +1,4 @@
  -/*-- $Id: ASCII85Filter.java,v 1.1 2000/12/18 02:28:31 kellyc Exp $ -- 
  +/*-- $Id: ASCII85Filter.java,v 1.2 2001/02/01 09:08:08 kellyc Exp $ -- 
   
    ============================================================================
                      The Apache Software License, Version 1.1
  @@ -79,105 +79,132 @@
       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");
  +	    
  +	}
  +	// 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));
   	}
  -	buffer.append(ASCII85_EOD);
  -	return buffer.toString().getBytes();
  +	*/	
  +	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);
   	    	    
   	}	
       }