Here's the output from `cvs diff` as well as the new files (how do I
get a diff or patch equivalent for files that are new? I can't `cvs
add` since I don't have write access, and it ignores non-cvs files) 

This patch:
1) adds a new class, org.apache.fop.util.StreamUtilities, that
provides some buffered stream copying routines - InputStream to
OutputStream. Adapted from my own IOLib, nice and fast and clean. Used
by several of the new classes.

2) modifies the current behavior of PDFFilters to operate on streams
instead of byte arrays.

3) changes the type of the ByteArrayOutputStream _data field of PDFStream to a new
abstract class, StreamCache

4) Added two implementations of StreamCache, InMemoryStreamCache and
TempFileStreamCache. The InMemory behaves much like the current FOP
implementation, with a ByteArrayOutputStream. The TempFile
implementation uses temp files.

5) a static factory method, PDFStream.createStreamCache(), creates the
desired type. Another static method,
PDFStream.setCacheToFile(boolean), sets which to use. 

Other StreamCache implementations are certainly possible; perhaps a
smart one that only caches to file when a certain size is reached
(StreamUtilities.BUFFER_SIZE perhaps). The problem with such a
solution is death-of-a-thousand-paper-cuts - you may have quite a few
small StreamCaches that end up killing scalability anyway.

Note that I was not able to test these changes - the current
cvs fop does not run and says so plainly. Is there some way I can run some
basic sanity tests at least? I would like to do some memory audits (we
own a seat of OptimizeIt) but need to be able to run some real-life
examples.

Thanks...

-- 

Paul Reavis                                      [EMAIL PROTECTED]
Design Lead
Partner Software, Inc.                        http://www.partnersoft.com
? src/org/apache/fop/pdf/InMemoryStreamCache.java
? src/org/apache/fop/pdf/StreamCache.java
? src/org/apache/fop/pdf/TempFileStreamCache.java
? src/org/apache/fop/util/StreamUtilities.java
Index: src/org/apache/fop/pdf/ASCII85Filter.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/ASCII85Filter.java,v
retrieving revision 1.3
diff -c -r1.3 ASCII85Filter.java
*** src/org/apache/fop/pdf/ASCII85Filter.java   30 Jul 2001 20:29:29 -0000      1.3
--- src/org/apache/fop/pdf/ASCII85Filter.java   23 May 2002 16:57:08 -0000
***************
*** 9,14 ****
--- 9,15 ----
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
+ import java.io.*;
  
  public class ASCII85Filter extends PDFFilter {
      private static final char ASCII85_ZERO = 'z';
***************
*** 30,38 ****
          return null;
      }
  
!     public byte[] encode(byte[] data) {
! 
!         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  
          int i;
          int total = 0;
--- 31,37 ----
          return null;
      }
  
!     public void encode(InputStream in, OutputStream out, int length) throws 
IOException {
  
          int i;
          int total = 0;
***************
*** 40,55 ****
  
          // 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) {
  
!             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);
  
          }
  
--- 39,54 ----
  
          // first encode the majority of the data
          // each 4 byte group becomes a 5 byte group
!         for (i = 0; i + 3 < length; i += 4) {
  
!             long val = ((in.read() << 24)
                          & 0xff000000L)          // note: must have the L at the
!             + ((in.read() << 16) & 0xff0000L)    // end, otherwise you get into
!             + ((in.read() << 8) & 0xff00L)    // weird signed value problems
!             + (in.read() & 0xffL);            // cause we're using a full 32 bits
              byte[] conv = convertWord(val);
  
!             out.write(conv, 0, conv.length);
  
          }
  
***************
*** 57,68 ****
          // 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[] lastdata = new byte[4];
              for (int j = 0; j < 4; j++) {
                  if (j < n) {
!                     lastdata[j] = data[i++];
                  } else {
                      lastdata[j] = 0;
                  }
--- 56,67 ----
          // 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 < length) {
!             int n = length - i;
              byte[] lastdata = new byte[4];
              for (int j = 0; j < 4; j++) {
                  if (j < n) {
!                     lastdata[j] = (byte)in.read();
                  } else {
                      lastdata[j] = 0;
                  }
***************
*** 82,99 ****
                  }
              }
              // 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);
--- 81,95 ----
                  }
              }
              // assert n+1 <= 5
!             out.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
!         out.write(ASCII85_EOD.getBytes(), 0,
                       ASCII85_EOD.getBytes().length);
  
  
          // assert that we have the correct outgoing length
          /*
           * int in = (data.length % 4);
***************
*** 103,110 ****
           * 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;
  
      }
  
      /**
--- 99,106 ----
           * 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));
           * }
           */
  
+         out.close();
      }
  
      /**
Index: src/org/apache/fop/pdf/ASCIIHexFilter.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/ASCIIHexFilter.java,v
retrieving revision 1.2
diff -c -r1.2 ASCIIHexFilter.java
*** src/org/apache/fop/pdf/ASCIIHexFilter.java  30 Jul 2001 20:29:29 -0000      1.2
--- src/org/apache/fop/pdf/ASCIIHexFilter.java  23 May 2002 16:57:08 -0000
***************
*** 8,13 ****
--- 8,14 ----
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
+ import java.io.*;
  
  public class ASCIIHexFilter extends PDFFilter {
      private static final String ASCIIHEX_EOD = ">";
***************
*** 21,39 ****
          return null;
      }
  
!     public byte[] encode(byte[] data) {
! 
!         StringBuffer buffer = new StringBuffer();
!         for (int i = 0; i < data.length; i++) {
!             int val = (int)(data[i] & 0xFF);
              if (val < 16)
!                 buffer.append("0");
!             buffer.append(Integer.toHexString(val));
          }
!         buffer.append(ASCIIHEX_EOD);
! 
!         return buffer.toString().getBytes();
! 
      }
  
  }
--- 22,37 ----
          return null;
      }
  
!     public void encode(InputStream in, OutputStream out, int length) throws 
IOException {
!         Writer writer = new OutputStreamWriter(out);
!         for (int i = 0; i < length; i++) {
!             int val = (int)(in.read() & 0xFF);
              if (val < 16)
!                 writer.write("0");
!             writer.write(Integer.toHexString(val));
          }
!         writer.write(ASCIIHEX_EOD);
!         writer.close();
      }
  
  }
Index: src/org/apache/fop/pdf/DCTFilter.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/DCTFilter.java,v
retrieving revision 1.1
diff -c -r1.1 DCTFilter.java
*** src/org/apache/fop/pdf/DCTFilter.java       18 Sep 2001 08:17:08 -0000      1.1
--- src/org/apache/fop/pdf/DCTFilter.java       23 May 2002 16:57:08 -0000
***************
*** 7,15 ****
  
  package org.apache.fop.pdf;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
! 
  
  /**
   * DCT Filter class. Right now it is just used as a dummy filter flag so
--- 7,17 ----
  
  package org.apache.fop.pdf;
  
+ import org.apache.fop.util.StreamUtilities;
+ 
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
! import java.io.*;
  
  /**
   * DCT Filter class. Right now it is just used as a dummy filter flag so
***************
*** 28,35 ****
          return null;
      }
  
!     public byte[] encode(byte[] data) {
!         return data;
      }
  }
  
--- 30,39 ----
          return null;
      }
  
!     public void encode(InputStream in, OutputStream out, int length) throws 
IOException {
!         StreamUtilities.streamCopy(in, out, length);
!         out.close();
      }
+     
  }
  
Index: src/org/apache/fop/pdf/FlateFilter.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/FlateFilter.java,v
retrieving revision 1.3
diff -c -r1.3 FlateFilter.java
*** src/org/apache/fop/pdf/FlateFilter.java     22 Nov 2001 07:11:40 -0000      1.3
--- src/org/apache/fop/pdf/FlateFilter.java     23 May 2002 16:57:08 -0000
***************
*** 7,15 ****
--- 7,18 ----
  
  package org.apache.fop.pdf;
  
+ import org.apache.fop.util.StreamUtilities;
+ 
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.util.zip.DeflaterOutputStream;
+ import java.io.*;
  
  /**
   * A filter to deflate a stream. Note that the attributes for
***************
*** 66,78 ****
       * because these attributes are not supported. So the DecodeParms
       * should be retrieved after calling this method.
       */
!     public byte[] encode(byte[] data) {
!         ByteArrayOutputStream outArrayStream = new ByteArrayOutputStream();
          _predictor = PREDICTION_NONE;
          try {
              DeflaterOutputStream compressedStream =
!                 new DeflaterOutputStream(outArrayStream);
!             compressedStream.write(data, 0, data.length);
              compressedStream.flush();
              compressedStream.close();
          } catch (IOException e) {
--- 69,80 ----
       * because these attributes are not supported. So the DecodeParms
       * should be retrieved after calling this method.
       */
!     public void encode(InputStream in, OutputStream out, int length) throws 
IOException {
          _predictor = PREDICTION_NONE;
          try {
              DeflaterOutputStream compressedStream =
!                 new DeflaterOutputStream(out);
!             StreamUtilities.streamCopy(in, compressedStream, length);
              compressedStream.flush();
              compressedStream.close();
          } catch (IOException e) {
***************
*** 80,86 ****
              //        + e.getMessage(), e);
          }
  
-         return outArrayStream.toByteArray();
      }
  
      public void setPredictor(int predictor) throws PDFFilterException {
--- 82,87 ----
Index: src/org/apache/fop/pdf/PDFFilter.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/PDFFilter.java,v
retrieving revision 1.3
diff -c -r1.3 PDFFilter.java
*** src/org/apache/fop/pdf/PDFFilter.java       30 Jul 2001 20:29:29 -0000      1.3
--- src/org/apache/fop/pdf/PDFFilter.java       23 May 2002 16:57:08 -0000
***************
*** 11,16 ****
--- 11,18 ----
  
  package org.apache.fop.pdf;
  
+ import java.io.*;
+ 
  public abstract class PDFFilter {
      /*
       * These are no longer needed, but are here as a reminder about what
***************
*** 60,67 ****
      /**
       * encode the given data with the filter
       */
!     public abstract byte[] encode(byte[] data);
! 
! 
  
  }
--- 62,67 ----
      /**
       * encode the given data with the filter
       */
!     public abstract void encode(InputStream in, OutputStream out, int length) throws 
IOException;
  
  }
Index: src/org/apache/fop/pdf/PDFICCStream.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/PDFICCStream.java,v
retrieving revision 1.1
diff -c -r1.1 PDFICCStream.java
*** src/org/apache/fop/pdf/PDFICCStream.java    16 Nov 2001 19:36:40 -0000      1.1
--- src/org/apache/fop/pdf/PDFICCStream.java    23 May 2002 16:57:09 -0000
***************
*** 11,17 ****
  public class PDFICCStream extends PDFStream {
      private int origLength;
      private int len1, len3;
-     private byte[] originalData = null;
      
      private ColorSpace cs;
      
--- 11,16 ----
***************
*** 43,49 ****
          if (cs.getColorSpace() > 0)
              pb.append("/Alternate /").append(cs.getColorSpacePDFString()).append(" 
");
          
!         pb.append("/Length ").append((_data.size() + 1)).append(" 
").append(filterEntry);
          pb.append(" >>\n");
          byte[] p = pb.toString().getBytes();
          stream.write(p);
--- 42,48 ----
          if (cs.getColorSpace() > 0)
              pb.append("/Alternate /").append(cs.getColorSpacePDFString()).append(" 
");
          
!         pb.append("/Length ").append((_data.getSize() + 1)).append(" 
").append(filterEntry);
          pb.append(" >>\n");
          byte[] p = pb.toString().getBytes();
          stream.write(p);
Index: src/org/apache/fop/pdf/PDFStream.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/PDFStream.java,v
retrieving revision 1.12
diff -c -r1.12 PDFStream.java
*** src/org/apache/fop/pdf/PDFStream.java       22 Nov 2001 07:11:40 -0000      1.12
--- src/org/apache/fop/pdf/PDFStream.java       23 May 2002 16:57:09 -0000
***************
*** 27,33 ****
      /**
       * the stream of PDF commands
       */
!     protected ByteArrayOutputStream _data;
  
      /**
       * the filters that should be applied
--- 27,33 ----
      /**
       * the stream of PDF commands
       */
!     protected StreamCache _data;
  
      /**
       * the filters that should be applied
***************
*** 41,47 ****
       */
      public PDFStream(int number) {
          super(number);
!         _data = new ByteArrayOutputStream();
          _filters = new ArrayList();
      }
  
--- 41,47 ----
       */
      public PDFStream(int number) {
          super(number);
!         _data = StreamCache.createStreamCache();
          _filters = new ArrayList();
      }
  
***************
*** 52,58 ****
       */
      public void add(String s) {
          try {
!             _data.write(s.getBytes());
          } catch (IOException ex) {
              ex.printStackTrace();
          }
--- 52,58 ----
       */
      public void add(String s) {
          try {
!             _data.getOutputStream().write(s.getBytes());
          } catch (IOException ex) {
              ex.printStackTrace();
          }
***************
*** 130,167 ****
                      int g = (p >> 8) & 0xFF;
                      int b = (p) & 0xFF;
                      if (r < 16) {
!                         _data.write('0');
                      }
!                     _data.write(Integer.toHexString(r).getBytes());
                      if (g < 16) {
!                         _data.write('0');
                      }
!                     _data.write(Integer.toHexString(g).getBytes());
                      if (b < 16) {
!                         _data.write('0');
                      }
!                     _data.write(Integer.toHexString(b).getBytes());
!                     _data.write(' ');
                  }
              }
!             _data.write(">\n".getBytes());
          } catch (IOException ex) {
              ex.printStackTrace();
          }
  
      }
  
      public void setData(byte[] data) throws IOException {
          _data.reset();
!         _data.write(data);
      }
  
      public byte[] getData() {
          return _data.toByteArray();
      }
  
      public int getDataLength() {
!         return _data.size();
      }
  
  
--- 130,174 ----
                      int g = (p >> 8) & 0xFF;
                      int b = (p) & 0xFF;
                      if (r < 16) {
!                         _data.getOutputStream().write('0');
                      }
!                     _data.getOutputStream().write(Integer.toHexString(r).getBytes());
                      if (g < 16) {
!                         _data.getOutputStream().write('0');
                      }
!                     _data.getOutputStream().write(Integer.toHexString(g).getBytes());
                      if (b < 16) {
!                         _data.getOutputStream().write('0');
                      }
!                     _data.getOutputStream().write(Integer.toHexString(b).getBytes());
!                     _data.getOutputStream().write(' ');
                  }
              }
!             _data.getOutputStream().write(">\n".getBytes());
          } catch (IOException ex) {
              ex.printStackTrace();
          }
  
      }
  
+     /*
      public void setData(byte[] data) throws IOException {
          _data.reset();
!         _data.getOutputStream().write(data);
      }
  
      public byte[] getData() {
          return _data.toByteArray();
      }
+     */
  
      public int getDataLength() {
!         try {
!             return _data.getSize();
!         } catch (Exception e) {
!             e.printStackTrace();
!             return 0;
!         }
      }
  
  
***************
*** 188,201 ****
          throw new RuntimeException();
      }
  
- 
      // overload the base object method so we don't have to copy
      // byte arrays around so much
      protected int output(OutputStream stream) throws IOException {
          int length = 0;
          String filterEntry = applyFilters();
          byte[] p = (this.number + " " + this.generation + " obj\n<< /Length "
!                     + (_data.size() + 1) + " " + filterEntry
                      + " >>\n").getBytes();
  
          stream.write(p);
--- 195,207 ----
          throw new RuntimeException();
      }
  
      // overload the base object method so we don't have to copy
      // byte arrays around so much
      protected int output(OutputStream stream) throws IOException {
          int length = 0;
          String filterEntry = applyFilters();
          byte[] p = (this.number + " " + this.generation + " obj\n<< /Length "
!                     + (_data.getSize() + 1) + " " + filterEntry
                      + " >>\n").getBytes();
  
          stream.write(p);
***************
*** 216,223 ****
          byte[] p = "stream\n".getBytes();
          stream.write(p);
          length += p.length;
!         _data.writeTo(stream);
!         length += _data.size();
          p = "\nendstream\n".getBytes();
          stream.write(p);
          length += p.length;
--- 222,230 ----
          byte[] p = "stream\n".getBytes();
          stream.write(p);
          length += p.length;
!         _data.outputStreamData(stream);
!         _data.close();
!         length += _data.getSize();
          p = "\nendstream\n".getBytes();
          stream.write(p);
          length += p.length;
***************
*** 243,251 ****
                  PDFFilter filter = (PDFFilter)_filters.get(count);
                  // apply the filter encoding if neccessary
                  if (!filter.isApplied()) {
!                     byte[] tmp = filter.encode(_data.toByteArray());
!                     _data.reset();
!                     _data.write(tmp);
                      filter.setApplied(true);
                  }
                  // place the names in our local vector in reverse order
--- 250,256 ----
                  PDFFilter filter = (PDFFilter)_filters.get(count);
                  // apply the filter encoding if neccessary
                  if (!filter.isApplied()) {
!                     _data.applyFilter(filter);
                      filter.setApplied(true);
                  }
                  // place the names in our local vector in reverse order
Index: src/org/apache/fop/pdf/PDFTTFStream.java
===================================================================
RCS file: /home/cvspublic/xml-fop/src/org/apache/fop/pdf/PDFTTFStream.java,v
retrieving revision 1.2
diff -c -r1.2 PDFTTFStream.java
*** src/org/apache/fop/pdf/PDFTTFStream.java    30 Jul 2001 20:29:30 -0000      1.2
--- src/org/apache/fop/pdf/PDFTTFStream.java    23 May 2002 16:57:09 -0000
***************
*** 23,29 ****
          String filterEntry = applyFilters();
          String preData = new String(this.number + " " + this.generation
                                      + " obj\n<< /Length "
!                                     + (_data.size() + 1) + " " + filterEntry
                                      + " " + "/Length1 " + origLength
                                      + " >>\n");
  
--- 23,29 ----
          String filterEntry = applyFilters();
          String preData = new String(this.number + " " + this.generation
                                      + " obj\n<< /Length "
!                                     + (_data.getSize() + 1) + " " + filterEntry
                                      + " " + "/Length1 " + origLength
                                      + " >>\n");
  

Attachment: fop-StreamCache.tar.gz
Description: Binary data

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

Reply via email to