DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11357>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11357

ASCII85Filter.convertWord() method does not work properly within specific environment

           Summary: ASCII85Filter.convertWord() method does not work
                    properly within specific environment
           Product: Fop
           Version: all
          Platform: All
        OS/Version: Linux
            Status: NEW
          Severity: Blocker
          Priority: Other
         Component: pdf renderer
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


The following bug occurs only within the following test environment:
OS Linux SuSE 7.3 (i386) Kernel version 2.4.10
JRE 1.3.1 Standard Edition, Classic VM (build 1.3.1, J2RE 1.3.1 IBM build 
cxia32131w-20020410 ORB130)

The bug (which is located within the JVM but can be solved by changing the 
method ASCII85Filter.convertWord()) causes the stated method to calculate 
invalid valus for c1 - c5, and a number of "illegal char value " texts are 
written to the screen.
The reason is that the IBM JVM has (sometimes!, not always) problems with long 
values between [0x7FFF FFFF .. 0xFFFF FFFF]. As a result the line
byte c1 = (byte)((word / base85_1) & 0xFF);
returns negative values for c1 (word and base85_1 are positive of course).
As mentioned, this error does not occur always, even with the same number. It 
also depends on the position of the number within the byte array passed to 
encode().

To solve this problem I changed the ASCII85Filter.convertWord() method:

  private static final double dbase85_4 = (double)85;
  private static final double dbase85_3 = base85_4 * base85_4;
  private static final double dbase85_2 = base85_3 * base85_4;
  private static final double dbase85_1 = base85_2 * base85_4;

  private static byte[] convertWord(long word) 
  {
    byte[] ret = null;

    word = word & 0xffffffffL;
    if (word < 0)
      word = -word;

    if (word == 0) 
    {
      byte[] result = {(byte)ASCII85_ZERO};
      return result;
    }
 
    byte c1 = 0;
    byte c2 = 0;
    byte c3 = 0;
    byte c4 = 0;
    byte c5 = 0;

// Use a different method to calculate c1-c5 if word is >= 2**31
    if (word > 0x7fffffffL)
    {
      double dword = (double)word;
      c1 = (byte)(((long)(dword / base85_1)) & 0xFF);
      double d1 = (double)c1 * dbase85_1;
      c2 = (byte)(((long)((dword - d1) / base85_2)) & 0xFF);
      d1 = d1 + ((double)c2 * dbase85_2);
      c3 = (byte)(((long)((dword - d1) / base85_3)) & 0xFF);
      d1 = d1 + ((double)c3 * dbase85_3);
      c4 = (byte)(((long)((dword - d1) / base85_4)) & 0xFF);
      d1 = d1 + ((double)c4 * dbase85_4);
      c5 = (byte)(((long)(dword - d1)) & 0xFF);
    }
    else
    {
      c1 = (byte)((word / base85_1) & 0xFF);
      long l1 = c1 * base85_1;
      c2 = (byte)(((word - l1) / base85_2) & 0xFF);
      l1 = l1 + (c2 * base85_2);
      c3 = (byte)(((word - l1) / base85_3) & 0xFF);
      l1 = l1 + (c3 * base85_3);
      c4 = (byte)(((word - l1) / base85_4) & 0xFF);
      l1 = l1 + (c4 * base85_4);
      c5 = (byte)(((word - l1)) & 0xFF);
    }

    ret = new byte[] {(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;
  }

Some additional notes:
* I think this bug also explains the bug report 11277
* I wonder why this method contains
    word = word & 0xffffffffL;
    if (word < 0)
      word = -word;
which I did not change, however if everything would work as expected you might 
think that this lines are senseless.
* For critical numbers (bit 31 is 1) the calculation of c1-c5 is done using 
double values instead of long. For smaller numbers the original algorithm is 
used. I removed the duplicate sub-calculations by introducing the d1/l1 
variables, maybe this speeds up performance a bit.

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

Reply via email to