Hello,

I was using iText to convert a JTable to a PDF. This was consuming a large amount of memory and taking a long time, so I did some memory profiling and have attached a patch that significantly improves performance for us. The following describes what I found, and what the patch does:

   When printing a JTable, you have to construct a lot of child
   PdfGraphics2D objects. For each child, the following happens:

      1. A BufferedImage is created just so that we can get a regular
         Graphics2D. This Graphics2D object may never be used, so I
         patched PdfGraphics2D to construct it only if needed.
      2. Two arrays of PdfGState are created, but are then replaced
         with the parent's arrays. I patched PdfGraphics2D to create
         these arrays in the non-private constructor. You might want to
         consider using the clone() method instead of keeping that
         private constructor around. The normal .clone() behaviour is
         very similar to what you have done manually in the .create()
         method.

   Finally, I noticed that the AWT PathIterator.currentSegment(float[])
   method creates a double[] internally. That is because the
   float[]-based method just passes through to the double[]-based
   method. I modified your use of the PathIterator to take this into
   account.

Can this patch be included in the next release?

Also, I am working on a commercial product. Can you clarify for me whether or not iText PDF can be included as a .jar in our commercial (non-open-source) product? I cannot remember whether "using a .jar" is considered a derivative work or not. If we're allowed to use it, then I will probably do a little more work on improving performance of iText and will send that on.

Thanks,
Peter.

Index: src/core/com/itextpdf/text/pdf/PdfGraphics2D.java
===================================================================
--- src/core/com/itextpdf/text/pdf/PdfGraphics2D.java   (revision 4347)
+++ src/core/com/itextpdf/text/pdf/PdfGraphics2D.java   (working copy)
@@ -149,7 +149,7 @@
 
     private boolean kid = false;
 
-    private Graphics2D dg2 = new BufferedImage(2, 2, 
BufferedImage.TYPE_INT_RGB).createGraphics();
+    private Graphics2D dg2;
 
     private boolean onlyShapes = false;
 
@@ -162,8 +162,8 @@
     // Added by Jurij Bilas
     protected boolean underline;          // indicates if the font style is 
underlined
 
-    protected PdfGState fillGState[] = new PdfGState[256];
-    protected PdfGState strokeGState[] = new PdfGState[256];
+    protected PdfGState fillGState[];
+    protected PdfGState strokeGState[];
     protected int currentFillGState = 255;
     protected int currentStrokeGState = 255;
 
@@ -180,11 +180,18 @@
 
        // Added by Alexej Suchov
        private Paint realPaint;
+       
+       private Graphics2D getDG2() {
+               if (dg2 == null) {
+                   dg2 = new BufferedImage(2, 2, 
BufferedImage.TYPE_INT_RGB).createGraphics();         
+               dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+               setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+               setRenderingHint(HyperLinkKey.KEY_INSTANCE, 
HyperLinkKey.VALUE_HYPERLINKKEY_OFF);
+               }
+               return dg2;
+       }
 
     private PdfGraphics2D() {
-        dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-        setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-        setRenderingHint(HyperLinkKey.KEY_INSTANCE, 
HyperLinkKey.VALUE_HYPERLINKKEY_OFF);
     }
 
     /**
@@ -193,9 +200,8 @@
      */
     PdfGraphics2D(PdfContentByte cb, float width, float height, FontMapper 
fontMapper, boolean onlyShapes, boolean convertImagesToJPEG, float quality) {
         super();
-        dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-        setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-        setRenderingHint(HyperLinkKey.KEY_INSTANCE, 
HyperLinkKey.VALUE_HYPERLINKKEY_OFF);
+        this.fillGState = new PdfGState[256];
+        this.strokeGState = new PdfGState[256];
         this.convertImagesToJPEG = convertImagesToJPEG;
         this.jpegQuality = quality;
         this.onlyShapes = onlyShapes;
@@ -589,7 +595,7 @@
      */
     @Override
     public GraphicsConfiguration getDeviceConfiguration() {
-        return dg2.getDeviceConfiguration();
+        return getDG2().getDeviceConfiguration();
     }
 
     /**
@@ -1058,7 +1064,7 @@
      */
     @Override
     public FontMetrics getFontMetrics(Font f) {
-        return dg2.getFontMetrics(f);
+        return getDG2().getFontMetrics(f);
     }
 
     /**
@@ -1356,7 +1362,8 @@
             disposeCalled = true;
             cb.restoreState();
             cb.restoreState();
-            dg2.dispose();
+            if (dg2 != null)
+               dg2.dispose();
             dg2 = null;
             if (kids != null) {
                 ByteBuffer buf = new ByteBuffer();
@@ -1379,7 +1386,8 @@
                 g2.cb.restoreState();
                 g2.cb.restoreState();
                 buf.append(buf2.getBuffer(), last, pos - last);
-                g2.dg2.dispose();
+                if (g2.dg2 != null)
+                       g2.dg2.dispose();
                 g2.dg2 = null;
                 g2.internalDispose(buf);
                 last = pos;
@@ -1419,9 +1427,17 @@
         else
             points = s.getPathIterator(transform);
         float[] coords = new float[6];
+       double dcoords[] = new double[6];
         while(!points.isDone()) {
             ++traces;
-            int segtype = points.currentSegment(coords);
+               int segtype = points.currentSegment(dcoords);
+               int numpoints = (segtype == PathIterator.SEG_CLOSE ? 0
+                                : (segtype == PathIterator.SEG_QUADTO ? 2
+                                   : (segtype == PathIterator.SEG_CUBICTO ? 3
+                                      : 1)));
+               for (int i = 0; i < numpoints * 2; i++) {
+                   coords[i] = (float) dcoords[i];
+               }            
             normalizeY(coords);
             switch(segtype) {
                 case PathIterator.SEG_CLOSE:
------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
iText-questions mailing list
iText-questions@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions

Buy the iText book: http://www.1t3xt.com/docs/book.php
Check the site with examples before you ask questions: 
http://www.1t3xt.info/examples/
You can also search the keywords list: http://1t3xt.info/tutorials/keywords/

Reply via email to