extensions/net.sf.basedb.meludi/trunk/src/net/sf/basedb/meludi/pdf/PdfUtil.java

Code
Comments
Other
Rev Date Author Line
4706 19 Mar 18 olle 1 package net.sf.basedb.meludi.pdf;
4706 19 Mar 18 olle 2
4706 19 Mar 18 olle 3 import java.io.ByteArrayOutputStream;
4706 19 Mar 18 olle 4 import java.io.IOException;
4706 19 Mar 18 olle 5 import java.io.InputStream;
4706 19 Mar 18 olle 6 import java.io.OutputStream;
4706 19 Mar 18 olle 7 import java.net.URL;
4706 19 Mar 18 olle 8 import java.text.SimpleDateFormat;
4706 19 Mar 18 olle 9 import java.util.Map;
4706 19 Mar 18 olle 10
4706 19 Mar 18 olle 11 import net.sf.basedb.core.Application;
4706 19 Mar 18 olle 12 import net.sf.basedb.meludi.Meludi;
4706 19 Mar 18 olle 13 import net.sf.basedb.meludi.converter.DateToStringConverter;
4706 19 Mar 18 olle 14 import net.sf.basedb.util.FileUtil;
4706 19 Mar 18 olle 15
4706 19 Mar 18 olle 16 import com.itextpdf.awt.geom.AffineTransform;
4706 19 Mar 18 olle 17 import com.itextpdf.text.Document;
4706 19 Mar 18 olle 18 import com.itextpdf.text.DocumentException;
4706 19 Mar 18 olle 19 import com.itextpdf.text.Element;
4706 19 Mar 18 olle 20 import com.itextpdf.text.Image;
4706 19 Mar 18 olle 21 import com.itextpdf.text.PageSize;
4706 19 Mar 18 olle 22 import com.itextpdf.text.Rectangle;
4706 19 Mar 18 olle 23 import com.itextpdf.text.pdf.Barcode128;
4706 19 Mar 18 olle 24 import com.itextpdf.text.pdf.BaseFont;
4706 19 Mar 18 olle 25 import com.itextpdf.text.pdf.PdfContentByte;
4706 19 Mar 18 olle 26 import com.itextpdf.text.pdf.PdfImportedPage;
4706 19 Mar 18 olle 27 import com.itextpdf.text.pdf.PdfReader;
4706 19 Mar 18 olle 28 import com.itextpdf.text.pdf.PdfWriter;
4706 19 Mar 18 olle 29
4706 19 Mar 18 olle 30 /**
4706 19 Mar 18 olle 31   Utility class for working with PDF documents. We always work with
4706 19 Mar 18 olle 32   A4 documents (unless noted).
4706 19 Mar 18 olle 33
4706 19 Mar 18 olle 34   @author nicklas
4706 19 Mar 18 olle 35   @since 2.18
4706 19 Mar 18 olle 36 */
4706 19 Mar 18 olle 37 public class PdfUtil 
4706 19 Mar 18 olle 38 {
4706 19 Mar 18 olle 39
4706 19 Mar 18 olle 40   /**
4706 19 Mar 18 olle 41     DPI value used in coordinate system for PDF.
4706 19 Mar 18 olle 42   */
4706 19 Mar 18 olle 43   public static final float DPI = 72;
4706 19 Mar 18 olle 44   
4706 19 Mar 18 olle 45   /**
4706 19 Mar 18 olle 46     Full with in points for an A4 PDF document (595).
4706 19 Mar 18 olle 47   */
4706 19 Mar 18 olle 48   public static final float FULL_WIDTH = PageSize.A4.getWidth();
4706 19 Mar 18 olle 49
4706 19 Mar 18 olle 50   /**
4706 19 Mar 18 olle 51     Full height in points for an A4 PDF document (842).
4706 19 Mar 18 olle 52   */
4706 19 Mar 18 olle 53   public static final float FULL_HEIGHT =  PageSize.A4.getHeight();
4706 19 Mar 18 olle 54   
4706 19 Mar 18 olle 55   /**
4706 19 Mar 18 olle 56     Coordinate for the left margin in our documents (36).
4706 19 Mar 18 olle 57   */
4706 19 Mar 18 olle 58   public static final float MARGIN_LEFT = 36;
4706 19 Mar 18 olle 59   
4706 19 Mar 18 olle 60   /**
4706 19 Mar 18 olle 61     Coordinate for the right margin in our documents (559).
4706 19 Mar 18 olle 62   */
4706 19 Mar 18 olle 63   public static final float MARGIN_RIGHT = FULL_WIDTH - 36;
4706 19 Mar 18 olle 64   
4706 19 Mar 18 olle 65   /**
4706 19 Mar 18 olle 66     Coordinate for the bottom margin in our documents (36).
4706 19 Mar 18 olle 67   */
4706 19 Mar 18 olle 68   public static final float MARGIN_BOTTOM = 36;
4706 19 Mar 18 olle 69   
4706 19 Mar 18 olle 70   /**
4706 19 Mar 18 olle 71     Coordinate for the top margin in our documents (806).
4706 19 Mar 18 olle 72   */
4706 19 Mar 18 olle 73   public static final float MARGIN_TOP = FULL_HEIGHT - 36;    
4706 19 Mar 18 olle 74   
4706 19 Mar 18 olle 75   /**
4706 19 Mar 18 olle 76     Usable width in our documents when margins have been excluded.
4706 19 Mar 18 olle 77   */
4706 19 Mar 18 olle 78   public static final float WIDTH = MARGIN_RIGHT - MARGIN_LEFT;
4706 19 Mar 18 olle 79
4706 19 Mar 18 olle 80   /**
4706 19 Mar 18 olle 81     Usable height in our documents when margins have been excluded.
4706 19 Mar 18 olle 82   */
4706 19 Mar 18 olle 83   public static final float HEIGHT = MARGIN_TOP - MARGIN_BOTTOM;
4706 19 Mar 18 olle 84
4706 19 Mar 18 olle 85   
4706 19 Mar 18 olle 86   public static final DateToStringConverter FOOTER_DATE_FORMAT = 
4706 19 Mar 18 olle 87       new DateToStringConverter(new SimpleDateFormat("yyyy-MM-dd HH:mm"));
4706 19 Mar 18 olle 88   
4706 19 Mar 18 olle 89   /**
4706 19 Mar 18 olle 90     Convert a point size to inches (points / DPI).
4706 19 Mar 18 olle 91   */
4706 19 Mar 18 olle 92   public static float pointsToInches(float points)
4706 19 Mar 18 olle 93   {
4706 19 Mar 18 olle 94     return points / DPI;
4706 19 Mar 18 olle 95   }
4706 19 Mar 18 olle 96   
4706 19 Mar 18 olle 97   /**
4706 19 Mar 18 olle 98     Convert an inch size to points (inches * DPI).
4706 19 Mar 18 olle 99   */
4706 19 Mar 18 olle 100   public static float inchesToPoints(float inches)
4706 19 Mar 18 olle 101   {
4706 19 Mar 18 olle 102     return DPI * inches;
4706 19 Mar 18 olle 103   }
4706 19 Mar 18 olle 104   
4706 19 Mar 18 olle 105   private final Document pdf;
4706 19 Mar 18 olle 106   private final String title;
4706 19 Mar 18 olle 107   private final String creator;
4706 19 Mar 18 olle 108   private final PdfReader reader;
4706 19 Mar 18 olle 109   private PdfContentByte canvas;
4706 19 Mar 18 olle 110   
4706 19 Mar 18 olle 111   private BaseFont defaultFont;
4706 19 Mar 18 olle 112   private BaseFont boldFont;
4706 19 Mar 18 olle 113   
4706 19 Mar 18 olle 114   /**
4706 19 Mar 18 olle 115     Create a new PDF document.
4706 19 Mar 18 olle 116   */
4706 19 Mar 18 olle 117   public PdfUtil(String title, String creator)
4706 19 Mar 18 olle 118   {
4706 19 Mar 18 olle 119     this.pdf = new Document(PageSize.A4);
4706 19 Mar 18 olle 120     this.title = title;
4706 19 Mar 18 olle 121     this.creator = creator;
4706 19 Mar 18 olle 122     this.reader = null;
4706 19 Mar 18 olle 123     this.defaultFont = getDefaultFont();
4706 19 Mar 18 olle 124     this.boldFont = getBoldFont();
4706 19 Mar 18 olle 125   }
4706 19 Mar 18 olle 126   
4706 19 Mar 18 olle 127   /**
4706 19 Mar 18 olle 128     Create a new PDF document that is a copy
4706 19 Mar 18 olle 129     of an existing PDF file (first page only).
4706 19 Mar 18 olle 130     @since 3.7
4706 19 Mar 18 olle 131   */
4706 19 Mar 18 olle 132   public PdfUtil(InputStream existing)
4706 19 Mar 18 olle 133     throws IOException
4706 19 Mar 18 olle 134   {
4706 19 Mar 18 olle 135     this.reader = new PdfReader(existing);
4706 19 Mar 18 olle 136     Map<String, String> info = reader.getInfo();
4706 19 Mar 18 olle 137     
4706 19 Mar 18 olle 138     this.pdf = new Document(reader.getPageSize(1));
4706 19 Mar 18 olle 139     this.title = info.get("Title");
4706 19 Mar 18 olle 140     this.creator = info.get("Creator");
4706 19 Mar 18 olle 141     this.defaultFont = getDefaultFont();
4706 19 Mar 18 olle 142     this.boldFont = getBoldFont();
4706 19 Mar 18 olle 143   }
4706 19 Mar 18 olle 144   
4706 19 Mar 18 olle 145   /**
4706 19 Mar 18 olle 146     Get the underlying PDF document object.
4706 19 Mar 18 olle 147   */
4706 19 Mar 18 olle 148   public Document getDocument()
4706 19 Mar 18 olle 149   {
4706 19 Mar 18 olle 150     return pdf;
4706 19 Mar 18 olle 151   }
4706 19 Mar 18 olle 152
4706 19 Mar 18 olle 153   /**
4706 19 Mar 18 olle 154     Get the canvas we are adding content to. Can't
4706 19 Mar 18 olle 155     be used until {@link #open(OutputStream)} has been
4706 19 Mar 18 olle 156     called.
4706 19 Mar 18 olle 157   */
4706 19 Mar 18 olle 158   public PdfContentByte getCanvas()
4706 19 Mar 18 olle 159   {
4706 19 Mar 18 olle 160     return canvas;
4706 19 Mar 18 olle 161   }
4706 19 Mar 18 olle 162   
4706 19 Mar 18 olle 163   /**
4706 19 Mar 18 olle 164      Open the PDF document so that content can be added to it.
4706 19 Mar 18 olle 165      @param out The outputstream to write the PDF document to
4706 19 Mar 18 olle 166    */
4706 19 Mar 18 olle 167   public PdfContentByte open(OutputStream out)
4706 19 Mar 18 olle 168   {
4706 19 Mar 18 olle 169     return open(out, null);
4706 19 Mar 18 olle 170   }
4706 19 Mar 18 olle 171   
4706 19 Mar 18 olle 172   /**
4706 19 Mar 18 olle 173     Open the PDF document so that content can be added to it. If a password
4706 19 Mar 18 olle 174     is specified the PDF is encrypted using AES-256 encryption. The password
4706 19 Mar 18 olle 175     is the owner password. A random string is generated for the user password.
4706 19 Mar 18 olle 176       
4706 19 Mar 18 olle 177     @param out The outputstream to write the PDF document to
4706 19 Mar 18 olle 178     @param password If not null, the pdf if password protected and encrypted
4706 19 Mar 18 olle 179       with AES 256.
4706 19 Mar 18 olle 180     @since 3.7
4706 19 Mar 18 olle 181   */
4706 19 Mar 18 olle 182   public PdfContentByte open(OutputStream out, String password)
4706 19 Mar 18 olle 183   {
4706 19 Mar 18 olle 184     try
4706 19 Mar 18 olle 185     {
4706 19 Mar 18 olle 186       PdfWriter writer = PdfWriter.getInstance(pdf, out);
4706 19 Mar 18 olle 187       if (password != null)
4706 19 Mar 18 olle 188       {
4706 19 Mar 18 olle 189         writer.setEncryption(Application.generateRandomId(16).getBytes(), password.getBytes(), 0, PdfWriter.ENCRYPTION_AES_256);
4706 19 Mar 18 olle 190       }
4706 19 Mar 18 olle 191       pdf.addCreator("MeLuDI " + Meludi.VERSION + (creator != null ? " ("+creator+")" : ""));
4706 19 Mar 18 olle 192       pdf.addTitle(title);
4706 19 Mar 18 olle 193       pdf.open();
4706 19 Mar 18 olle 194       canvas = writer.getDirectContent();
4706 19 Mar 18 olle 195       
4706 19 Mar 18 olle 196       if (reader != null)
4706 19 Mar 18 olle 197       {
4706 19 Mar 18 olle 198         // Copy the first page of this document
4706 19 Mar 18 olle 199         importPdf(reader, 1, 0, 0, 1, 1);
4706 19 Mar 18 olle 200       }
4706 19 Mar 18 olle 201     }
4706 19 Mar 18 olle 202     catch (DocumentException ex)
4706 19 Mar 18 olle 203     {
4706 19 Mar 18 olle 204       throw new RuntimeException(ex);
4706 19 Mar 18 olle 205     }
4706 19 Mar 18 olle 206     return canvas;
4706 19 Mar 18 olle 207   }
4706 19 Mar 18 olle 208
4706 19 Mar 18 olle 209   /**
4706 19 Mar 18 olle 210     Close the PDF document.
4706 19 Mar 18 olle 211   */
4706 19 Mar 18 olle 212   public void close()
4706 19 Mar 18 olle 213   {
4706 19 Mar 18 olle 214     pdf.close();
4706 19 Mar 18 olle 215     if (reader != null) reader.close();
4706 19 Mar 18 olle 216   }
4706 19 Mar 18 olle 217
4706 19 Mar 18 olle 218   /**
4706 19 Mar 18 olle 219     Get page number of existing document.
4706 19 Mar 18 olle 220    */
4706 19 Mar 18 olle 221   public int getPageNumber()
4706 19 Mar 18 olle 222   {
4706 19 Mar 18 olle 223     return pdf.getPageNumber();
4706 19 Mar 18 olle 224   }
4706 19 Mar 18 olle 225
4706 19 Mar 18 olle 226   /**
4706 19 Mar 18 olle 227     Create a new page in existing document.
4706 19 Mar 18 olle 228    */
4706 19 Mar 18 olle 229   public void newPage()
4706 19 Mar 18 olle 230   {
4706 19 Mar 18 olle 231     pdf.newPage();
4706 19 Mar 18 olle 232   }
4706 19 Mar 18 olle 233
4706 19 Mar 18 olle 234   /**
4706 19 Mar 18 olle 235     Create a new blank page in existing document.
4706 19 Mar 18 olle 236    */
4706 19 Mar 18 olle 237   public void newBlankPage()
4706 19 Mar 18 olle 238   {
4706 19 Mar 18 olle 239     pdf.newPage();
4706 19 Mar 18 olle 240     // If not filled with other data, page must be set to be non-empty, to not be ignored.
4706 19 Mar 18 olle 241     PdfWriter writer = canvas.getPdfWriter();
4706 19 Mar 18 olle 242     writer.setPageEmpty(false);
4706 19 Mar 18 olle 243   }
4706 19 Mar 18 olle 244
4706 19 Mar 18 olle 245   /**
4706 19 Mar 18 olle 246     Create a font for text elements.
4706 19 Mar 18 olle 247     @see BaseFont for pre-defined font names
4706 19 Mar 18 olle 248   */
4706 19 Mar 18 olle 249   public BaseFont getDefaultFont()
4706 19 Mar 18 olle 250   {
4706 19 Mar 18 olle 251     if (defaultFont == null)
4706 19 Mar 18 olle 252     {
4706 19 Mar 18 olle 253       try
4706 19 Mar 18 olle 254       {
4706 19 Mar 18 olle 255         URL openSans = PdfUtil.class.getResource("/META-INF/fonts/OpenSans-Regular.ttf");
4706 19 Mar 18 olle 256         return BaseFont.createFont("jar:"+openSans.getPath(), BaseFont.IDENTITY_H, true);
4706 19 Mar 18 olle 257       }
4706 19 Mar 18 olle 258       catch (IOException | DocumentException ex)
4706 19 Mar 18 olle 259       {
4706 19 Mar 18 olle 260         throw new RuntimeException(ex);
4706 19 Mar 18 olle 261       }
4706 19 Mar 18 olle 262     }
4706 19 Mar 18 olle 263     return defaultFont;
4706 19 Mar 18 olle 264   }
4706 19 Mar 18 olle 265   
4706 19 Mar 18 olle 266   /**
4706 19 Mar 18 olle 267     Create a bold font for text elements.
4706 19 Mar 18 olle 268     @see BaseFont for pre-defined font names
4706 19 Mar 18 olle 269   */
4706 19 Mar 18 olle 270   public BaseFont getBoldFont()
4706 19 Mar 18 olle 271   {
4706 19 Mar 18 olle 272     if (boldFont == null)
4706 19 Mar 18 olle 273     {
4706 19 Mar 18 olle 274       try
4706 19 Mar 18 olle 275       {
4706 19 Mar 18 olle 276         URL openSans = PdfUtil.class.getResource("/META-INF/fonts/OpenSans-Bold.ttf");
4706 19 Mar 18 olle 277         return BaseFont.createFont("jar:"+openSans.getPath(), BaseFont.IDENTITY_H, true);
4706 19 Mar 18 olle 278       }
4706 19 Mar 18 olle 279       catch (IOException | DocumentException ex)
4706 19 Mar 18 olle 280       {
4706 19 Mar 18 olle 281         throw new RuntimeException(ex);
4706 19 Mar 18 olle 282       }
4706 19 Mar 18 olle 283     }
4706 19 Mar 18 olle 284     return boldFont;
4706 19 Mar 18 olle 285   }
4706 19 Mar 18 olle 286   
4706 19 Mar 18 olle 287   /**
4706 19 Mar 18 olle 288     Add text to the document.
4706 19 Mar 18 olle 289     
4706 19 Mar 18 olle 290     @param text The text to add
4706 19 Mar 18 olle 291     @param fontSize Font size to use
4706 19 Mar 18 olle 292     @param align Alignment
4706 19 Mar 18 olle 293     @param x X coordinate in points
4706 19 Mar 18 olle 294     @param y Y coordinate in points
4706 19 Mar 18 olle 295   */
4706 19 Mar 18 olle 296   public void addText(String text, float fontSize, int align, float x, float y)
4706 19 Mar 18 olle 297   {
4706 19 Mar 18 olle 298     if (text == null || text.equals("")) return;
4706 19 Mar 18 olle 299     canvas.beginText();
4706 19 Mar 18 olle 300     canvas.setFontAndSize(defaultFont, fontSize); 
4706 19 Mar 18 olle 301     canvas.showTextAligned(align, text, x, y, 0);
4706 19 Mar 18 olle 302     canvas.endText();
4706 19 Mar 18 olle 303   }
4706 19 Mar 18 olle 304   
4706 19 Mar 18 olle 305   /**
4706 19 Mar 18 olle 306     Add text to the document.
4706 19 Mar 18 olle 307
4706 19 Mar 18 olle 308     @param text The text to add
4706 19 Mar 18 olle 309     @param fontSize Font size to use
4706 19 Mar 18 olle 310     @param align Alignment
4706 19 Mar 18 olle 311     @param x X coordinate in points
4706 19 Mar 18 olle 312     @param y Y coordinate in points
4706 19 Mar 18 olle 313     @param rotation 
4706 19 Mar 18 olle 314   */
4706 19 Mar 18 olle 315   public void addText(String text, float fontSize, int align, float x, float y, float rotation)
4706 19 Mar 18 olle 316   {
4706 19 Mar 18 olle 317     if (text == null || text.equals("")) return;
4706 19 Mar 18 olle 318     canvas.beginText();
4706 19 Mar 18 olle 319     canvas.setFontAndSize(defaultFont, fontSize); 
4706 19 Mar 18 olle 320     canvas.showTextAligned(align, text, x, y, rotation);
4706 19 Mar 18 olle 321     canvas.endText();
4706 19 Mar 18 olle 322   }
4706 19 Mar 18 olle 323
4706 19 Mar 18 olle 324   /**
4706 19 Mar 18 olle 325     Add bold text to the document.
4706 19 Mar 18 olle 326     
4706 19 Mar 18 olle 327     @param text The text to add
4706 19 Mar 18 olle 328     @param fontSize Font size to use
4706 19 Mar 18 olle 329     @param align Alignment
4706 19 Mar 18 olle 330     @param x X coordinate in points
4706 19 Mar 18 olle 331     @param y Y coordinate in points
4706 19 Mar 18 olle 332   */
4706 19 Mar 18 olle 333   public void addBoldText(String text, float fontSize, int align, float x, float y)
4706 19 Mar 18 olle 334   {
4706 19 Mar 18 olle 335     if (text == null || text.equals("")) return;
4706 19 Mar 18 olle 336     canvas.beginText();
4706 19 Mar 18 olle 337     canvas.setFontAndSize(boldFont, fontSize); 
4706 19 Mar 18 olle 338     canvas.showTextAligned(align, text, x, y, 0);
4706 19 Mar 18 olle 339     canvas.endText();
4706 19 Mar 18 olle 340   }
4706 19 Mar 18 olle 341   
4706 19 Mar 18 olle 342   /**
4706 19 Mar 18 olle 343     Add bold text to the document.
4706 19 Mar 18 olle 344   
4706 19 Mar 18 olle 345     @param text The text to add
4706 19 Mar 18 olle 346     @param fontSize Font size to use
4706 19 Mar 18 olle 347     @param align Alignment
4706 19 Mar 18 olle 348     @param x X coordinate in points
4706 19 Mar 18 olle 349     @param y Y coordinate in points
4706 19 Mar 18 olle 350     @param rotation 
4706 19 Mar 18 olle 351   */
4706 19 Mar 18 olle 352   public void addBoldText(String text, float fontSize, int align, float x, float y, float rotation)
4706 19 Mar 18 olle 353   {
4706 19 Mar 18 olle 354     if (text == null || text.equals("")) return;
4706 19 Mar 18 olle 355     canvas.beginText();
4706 19 Mar 18 olle 356     canvas.setFontAndSize(boldFont, fontSize); 
4706 19 Mar 18 olle 357     canvas.showTextAligned(align, text, x, y, rotation);
4706 19 Mar 18 olle 358     canvas.endText();
4706 19 Mar 18 olle 359   }
4706 19 Mar 18 olle 360
4706 19 Mar 18 olle 361   /**
4706 19 Mar 18 olle 362     Draw grid line around the page. Major grid is 50pt, with minor at every 10pt and
4706 19 Mar 18 olle 363     ticks at every 2pt.
4706 19 Mar 18 olle 364    */
4706 19 Mar 18 olle 365   public void drawGrid()
4706 19 Mar 18 olle 366   {
4706 19 Mar 18 olle 367     // Along Y-axis
4706 19 Mar 18 olle 368     canvas.saveState();
4706 19 Mar 18 olle 369     canvas.setLineWidth(0.25f);
4706 19 Mar 18 olle 370     for (int y = 0; y < FULL_HEIGHT; y += 2)
4706 19 Mar 18 olle 371     {
4706 19 Mar 18 olle 372       int lineLength = y % 50 == 0 ? 15 : (y % 10 == 0 ? 10 : 5);
4706 19 Mar 18 olle 373       
4706 19 Mar 18 olle 374       canvas.moveTo(0, y);
4706 19 Mar 18 olle 375       canvas.lineTo(lineLength, y);
4706 19 Mar 18 olle 376       canvas.moveTo(PdfUtil.FULL_WIDTH-lineLength, y);
4706 19 Mar 18 olle 377       canvas.lineTo(PdfUtil.FULL_WIDTH, y);
4706 19 Mar 18 olle 378     }
4706 19 Mar 18 olle 379     
4706 19 Mar 18 olle 380     // Along Y axis
4706 19 Mar 18 olle 381     for (int x = 0; x < FULL_WIDTH; x += 2)
4706 19 Mar 18 olle 382     {
4706 19 Mar 18 olle 383       int lineLength = x % 50 == 0 ? 15 : (x % 10 == 0 ? 10 : 5);
4706 19 Mar 18 olle 384       canvas.moveTo(x, 0);
4706 19 Mar 18 olle 385       canvas.lineTo(x, lineLength);
4706 19 Mar 18 olle 386       canvas.moveTo(x, PdfUtil.FULL_HEIGHT-lineLength);
4706 19 Mar 18 olle 387       canvas.lineTo(x, PdfUtil.FULL_HEIGHT);
4706 19 Mar 18 olle 388       
4706 19 Mar 18 olle 389     }
4706 19 Mar 18 olle 390     
4706 19 Mar 18 olle 391     canvas.stroke();
4706 19 Mar 18 olle 392     canvas.restoreState();
4706 19 Mar 18 olle 393
4706 19 Mar 18 olle 394     BaseFont gridFont = getDefaultFont();
4706 19 Mar 18 olle 395     canvas.beginText();
4706 19 Mar 18 olle 396     canvas.setFontAndSize(gridFont, 8);
4706 19 Mar 18 olle 397     // Put labels on major grid lines
4706 19 Mar 18 olle 398     for (int y = 50; y < FULL_HEIGHT; y += 50)
4706 19 Mar 18 olle 399     {
4706 19 Mar 18 olle 400       canvas.showTextAligned(Element.ALIGN_LEFT, Integer.toString(y), 16, y-3, 0);
4706 19 Mar 18 olle 401       canvas.showTextAligned(Element.ALIGN_RIGHT, Integer.toString(y), FULL_WIDTH - 16, y-3, 0);
4706 19 Mar 18 olle 402     }
4706 19 Mar 18 olle 403     for (int x = 50; x < FULL_WIDTH; x += 50)
4706 19 Mar 18 olle 404     {
4706 19 Mar 18 olle 405       canvas.showTextAligned(Element.ALIGN_LEFT, Integer.toString(x), x+3, 16, 90);
4706 19 Mar 18 olle 406       canvas.showTextAligned(Element.ALIGN_RIGHT, Integer.toString(x), x+3, FULL_HEIGHT-16, 90);
4706 19 Mar 18 olle 407     }
4706 19 Mar 18 olle 408     canvas.endText(); 
4706 19 Mar 18 olle 409
4706 19 Mar 18 olle 410     
4706 19 Mar 18 olle 411   }
4706 19 Mar 18 olle 412
4706 19 Mar 18 olle 413   /**
4706 19 Mar 18 olle 414    * Creates a barcode with chosen content, width, and height,
4706 19 Mar 18 olle 415    * and returns an Image object of it. The barcode will be
4706 19 Mar 18 olle 416    * of type Code 128.
4706 19 Mar 18 olle 417    *  
4706 19 Mar 18 olle 418    * @param text String The text to encode in the barcode.
4706 19 Mar 18 olle 419    * @param width float Width of barcode.
4706 19 Mar 18 olle 420    * @param height float Height of barcode.
4706 19 Mar 18 olle 421    * @return Image An Image object for the created barcode,
4706 19 Mar 18 olle 422    */
4706 19 Mar 18 olle 423   private Image createBarcode(String text, float width, float height)
4706 19 Mar 18 olle 424   {
4706 19 Mar 18 olle 425     Barcode128 code128 = new Barcode128();
4706 19 Mar 18 olle 426     code128.setBaseline(-1);
4706 19 Mar 18 olle 427     code128.setFont(null);
4706 19 Mar 18 olle 428     code128.setSize(12);
4706 19 Mar 18 olle 429     code128.setCode(text);
4706 19 Mar 18 olle 430     code128.setCodeType(Barcode128.CODE128);
4706 19 Mar 18 olle 431     Rectangle rect = code128.getBarcodeSize();
4706 19 Mar 18 olle 432     Image code128Image = code128.createImageWithBarcode(canvas, null, null);
4706 19 Mar 18 olle 433     Rectangle targetRect = new Rectangle(0f, 0f, width, height);
4706 19 Mar 18 olle 434     code128Image.scaleToFit(targetRect);
4706 19 Mar 18 olle 435     return code128Image;
4706 19 Mar 18 olle 436   }
4706 19 Mar 18 olle 437
4706 19 Mar 18 olle 438   /**
4706 19 Mar 18 olle 439     Create a barcode image for the PDF document and place it at the location specified 
4706 19 Mar 18 olle 440     by the x and y coordinates. The image is stretched to fit within the given
4706 19 Mar 18 olle 441     width and height. It can be aligned either to Element.ALIGN_LEFT or
4706 19 Mar 18 olle 442     Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 443     The image is placed in front of existing images.
4706 19 Mar 18 olle 444   */
4706 19 Mar 18 olle 445   public void addBarcode(String text, float x, float y, float width, float height, int align)
4706 19 Mar 18 olle 446     throws IOException
4706 19 Mar 18 olle 447   {
4706 19 Mar 18 olle 448     float rotationDegrees = 0f;
4706 19 Mar 18 olle 449     addBarcode(text, x, y, width, height, align, rotationDegrees);
4706 19 Mar 18 olle 450   }
4706 19 Mar 18 olle 451
4706 19 Mar 18 olle 452   /**
4706 19 Mar 18 olle 453     Create a barcode image for the PDF document and place it at the location specified 
4706 19 Mar 18 olle 454     by the x and y coordinates. The image is stretched to fit within the given
4706 19 Mar 18 olle 455     width and height. It can be aligned either to Element.ALIGN_LEFT or
4706 19 Mar 18 olle 456     Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 457     The image is placed in front of existing images.
4706 19 Mar 18 olle 458   */
4706 19 Mar 18 olle 459   public void addBarcode(String text, float x, float y, float width, float height, int align, float rotationDegrees)
4706 19 Mar 18 olle 460     throws IOException
4706 19 Mar 18 olle 461   {
4706 19 Mar 18 olle 462     Image img = createBarcode(text, width, height);
4706 19 Mar 18 olle 463     importImage2(img, x, y, width, height, align, rotationDegrees);
4706 19 Mar 18 olle 464   }
4706 19 Mar 18 olle 465
4706 19 Mar 18 olle 466   /**
4706 19 Mar 18 olle 467    * Import a PDF document and place it at the location specified
4706 19 Mar 18 olle 468    * by the x and y coordinates. The imported document will be
4706 19 Mar 18 olle 469    * scaled to the height of the current document.
4706 19 Mar 18 olle 470    * 
4706 19 Mar 18 olle 471    * @param pdf InputStream The input stream of the PDF document to import.
4706 19 Mar 18 olle 472    * @param x float The left x start coordinate in point units.
4706 19 Mar 18 olle 473    * @param y float The bottom y start coordinate in point units
4706 19 Mar 18 olle 474    * @throws IOException
4706 19 Mar 18 olle 475    */
4706 19 Mar 18 olle 476   public void importPdf(InputStream pdf, float x, float y)
4706 19 Mar 18 olle 477     throws IOException
4706 19 Mar 18 olle 478   {
4706 19 Mar 18 olle 479     // Load existing PDF
4706 19 Mar 18 olle 480     importPdf(pdf, 1, x, y);
4706 19 Mar 18 olle 481   }
4706 19 Mar 18 olle 482
4706 19 Mar 18 olle 483   /**
4706 19 Mar 18 olle 484    * Import a PDF document and place it at the location specified
4706 19 Mar 18 olle 485    * by the x and y coordinates. The imported document will be
4706 19 Mar 18 olle 486    * scaled to the height of the current document.
4706 19 Mar 18 olle 487    * 
4706 19 Mar 18 olle 488    * @param pdf InputStream The input stream of the PDF document to import.
4706 19 Mar 18 olle 489    * @param pageNo int The page number for the imported PDF.
4706 19 Mar 18 olle 490    * @param x float The left x start coordinate in point units.
4706 19 Mar 18 olle 491    * @param y float The bottom y start coordinate in point units
4706 19 Mar 18 olle 492    * @throws IOException
4706 19 Mar 18 olle 493    */
4706 19 Mar 18 olle 494   public void importPdf(InputStream pdf, int pageNo, float x, float y)
4706 19 Mar 18 olle 495     throws IOException
4706 19 Mar 18 olle 496   {
4706 19 Mar 18 olle 497     // Load existing PDF
4706 19 Mar 18 olle 498     PdfReader reader = new PdfReader(pdf);
4706 19 Mar 18 olle 499     importPdf(reader, pageNo, x, y);
4706 19 Mar 18 olle 500   }
4706 19 Mar 18 olle 501
4706 19 Mar 18 olle 502   /**
4706 19 Mar 18 olle 503    * Import a PDF document and place it at the location specified
4706 19 Mar 18 olle 504    * by the x and y coordinates.
4706 19 Mar 18 olle 505    * 
4706 19 Mar 18 olle 506    * @param pdf InputStream The input stream of the PDF document to import.
4706 19 Mar 18 olle 507    * @param pageNo int The page number for the imported PDF.
4706 19 Mar 18 olle 508    * @param x float The left x start coordinate in point units.
4706 19 Mar 18 olle 509    * @param y float The bottom y start coordinate in point units
4706 19 Mar 18 olle 510    * @param scaleX float The x direction scale factor.
4706 19 Mar 18 olle 511    * @param scaleY float The y direction scale factor.
4706 19 Mar 18 olle 512    * @throws IOException
4706 19 Mar 18 olle 513    */
4706 19 Mar 18 olle 514   public void importPdf(InputStream pdf, int pageNo, float x, float y, float scaleX, float scaleY)
4706 19 Mar 18 olle 515     throws IOException
4706 19 Mar 18 olle 516   {
4706 19 Mar 18 olle 517     // Load existing PDF
4706 19 Mar 18 olle 518     PdfReader reader = new PdfReader(pdf);
4706 19 Mar 18 olle 519     importPdf(reader, pageNo, x, y, scaleX, scaleY);
4706 19 Mar 18 olle 520   }
4706 19 Mar 18 olle 521
4706 19 Mar 18 olle 522   /**
4706 19 Mar 18 olle 523    * Import a PDF document and place it at the location specified
4706 19 Mar 18 olle 524    * by the x and y coordinates. The imported document will be
4706 19 Mar 18 olle 525    * scaled to the height of the current document.
4706 19 Mar 18 olle 526    * 
4706 19 Mar 18 olle 527    * @param reader PdfReader The PDF reader for the PDF input stream.
4706 19 Mar 18 olle 528    * @param pageNo int The page number for the imported PDF.
4706 19 Mar 18 olle 529    * @param x float The left x start coordinate in point units.
4706 19 Mar 18 olle 530    * @param y float The bottom y start coordinate in point units
4706 19 Mar 18 olle 531    */
4706 19 Mar 18 olle 532   private void importPdf(PdfReader reader, int pageNo, float x, float y)
4706 19 Mar 18 olle 533   {
4706 19 Mar 18 olle 534     PdfImportedPage page = canvas.getPdfWriter().getImportedPage(reader, pageNo);
4706 19 Mar 18 olle 535
4706 19 Mar 18 olle 536     // Scale document to the height of the current document
4706 19 Mar 18 olle 537     float scaleY = FULL_HEIGHT/page.getHeight();
4706 19 Mar 18 olle 538     float scaleX = scaleY;
4706 19 Mar 18 olle 539     
4706 19 Mar 18 olle 540     AffineTransform transform = new AffineTransform(scaleX, 0, 0, scaleY, x, y);
4706 19 Mar 18 olle 541     
4706 19 Mar 18 olle 542     // Copy page of existing PDF into output PDF
4706 19 Mar 18 olle 543     canvas.addTemplate(page, transform);
4706 19 Mar 18 olle 544   }
4706 19 Mar 18 olle 545   
4706 19 Mar 18 olle 546   /**
4706 19 Mar 18 olle 547     Import another PDF document and place it at the location specified 
4706 19 Mar 18 olle 548     by the x and y coordinates. The scaling factors can be used to
4706 19 Mar 18 olle 549     up or downscale the imported document. Use NaN to automatically
4706 19 Mar 18 olle 550     scale to width of current document. 
4706 19 Mar 18 olle 551   */
4706 19 Mar 18 olle 552   public void importPdf(InputStream pdf, float x, float y, float scaleX, float scaleY)
4706 19 Mar 18 olle 553     throws IOException
4706 19 Mar 18 olle 554   {
4706 19 Mar 18 olle 555     // Load existing PDF
4706 19 Mar 18 olle 556     PdfReader reader = new PdfReader(pdf);
4706 19 Mar 18 olle 557     importPdf(reader, 1, x, y, scaleX, scaleY);
4706 19 Mar 18 olle 558   }
4706 19 Mar 18 olle 559   
4706 19 Mar 18 olle 560   private void importPdf(PdfReader reader, int pageNo, float x, float y, float scaleX, float scaleY)
4706 19 Mar 18 olle 561   {
4706 19 Mar 18 olle 562     PdfImportedPage page = canvas.getPdfWriter().getImportedPage(reader, pageNo); 
4706 19 Mar 18 olle 563
4706 19 Mar 18 olle 564     if (Float.isNaN(scaleX)) scaleX = WIDTH / page.getWidth();
4706 19 Mar 18 olle 565     if (Float.isNaN(scaleY)) scaleY = scaleX;
4706 19 Mar 18 olle 566
4706 19 Mar 18 olle 567     AffineTransform transform = new AffineTransform(scaleX, 0, 0, scaleY, x, y);
4706 19 Mar 18 olle 568     
4706 19 Mar 18 olle 569     // Copy page of existing PDF into output PDF
4706 19 Mar 18 olle 570     canvas.addTemplate(page, transform);
4706 19 Mar 18 olle 571   }
4706 19 Mar 18 olle 572   
4706 19 Mar 18 olle 573   /**
4706 19 Mar 18 olle 574     Import an image into the PDF document and place it at the location specified 
4706 19 Mar 18 olle 575     by the x and y coordinates. The image is automatically scaled to fit within the
4706 19 Mar 18 olle 576     given width and height while preserving aspect ratio. It can be aligned either to
4706 19 Mar 18 olle 577     Element.ALIGN_LEFT or Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 578   */
4706 19 Mar 18 olle 579   public void importImage(InputStream image, float x, float y, float width, float height, int align)
4706 19 Mar 18 olle 580     throws IOException
4706 19 Mar 18 olle 581   {
4706 19 Mar 18 olle 582     ByteArrayOutputStream bytes = new ByteArrayOutputStream(4096);
4706 19 Mar 18 olle 583     try
4706 19 Mar 18 olle 584     {
4706 19 Mar 18 olle 585       FileUtil.copy(image, bytes);
4706 19 Mar 18 olle 586       bytes.close();
4706 19 Mar 18 olle 587       Image img = Image.getInstance(bytes.toByteArray());
4706 19 Mar 18 olle 588       if (Float.isNaN(width) && Float.isNaN(height))
4706 19 Mar 18 olle 589       {
4706 19 Mar 18 olle 590         width = img.getWidth();
4706 19 Mar 18 olle 591         height = img.getHeight();
4706 19 Mar 18 olle 592       }
4706 19 Mar 18 olle 593       else if (Float.isNaN(height))
4706 19 Mar 18 olle 594       {
4706 19 Mar 18 olle 595         float scale = width / img.getWidth();
4706 19 Mar 18 olle 596         height = scale * img.getHeight();
4706 19 Mar 18 olle 597       }
4706 19 Mar 18 olle 598       else if (Float.isNaN(width))
4706 19 Mar 18 olle 599       {
4706 19 Mar 18 olle 600         float scale = height / img.getHeight();
4706 19 Mar 18 olle 601         width = scale * img.getWidth();
4706 19 Mar 18 olle 602       }
4706 19 Mar 18 olle 603       else
4706 19 Mar 18 olle 604       {
4706 19 Mar 18 olle 605         float scale = Math.min(height / img.getHeight(), width / img.getWidth());
4706 19 Mar 18 olle 606         height = scale * img.getHeight();
4706 19 Mar 18 olle 607         width = scale * img.getWidth();
4706 19 Mar 18 olle 608       }
4706 19 Mar 18 olle 609       
4706 19 Mar 18 olle 610       if ((align & Element.ALIGN_RIGHT) > 0)
4706 19 Mar 18 olle 611       {
4706 19 Mar 18 olle 612         x -= width;
4706 19 Mar 18 olle 613       }
4706 19 Mar 18 olle 614       if ((align & Element.ALIGN_TOP) > 0)
4706 19 Mar 18 olle 615       {
4706 19 Mar 18 olle 616         y -= height;
4706 19 Mar 18 olle 617       }
4706 19 Mar 18 olle 618       
4706 19 Mar 18 olle 619       img.setAbsolutePosition(x, y);
4706 19 Mar 18 olle 620       img.scaleAbsolute(width, height);
4706 19 Mar 18 olle 621       pdf.add(img);
4706 19 Mar 18 olle 622     }
4706 19 Mar 18 olle 623     catch (DocumentException ex)
4706 19 Mar 18 olle 624     {
4706 19 Mar 18 olle 625       throw new IOException(ex);
4706 19 Mar 18 olle 626     }
4706 19 Mar 18 olle 627     finally
4706 19 Mar 18 olle 628     {
4706 19 Mar 18 olle 629       FileUtil.close(bytes);
4706 19 Mar 18 olle 630       FileUtil.close(image);
4706 19 Mar 18 olle 631     }
4706 19 Mar 18 olle 632   }
4706 19 Mar 18 olle 633
4706 19 Mar 18 olle 634   /**
4706 19 Mar 18 olle 635     Import an image into the PDF document and place it at the location specified 
4706 19 Mar 18 olle 636     by the x and y coordinates. The image is stretched to fit within the given
4706 19 Mar 18 olle 637     width and height. It can be aligned either to Element.ALIGN_LEFT or
4706 19 Mar 18 olle 638     Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 639     The image is placed in front of existing images.
4706 19 Mar 18 olle 640   */
4706 19 Mar 18 olle 641   public void importImage2(byte[] imageByteArray, float x, float y, float width, float height, int align)
4706 19 Mar 18 olle 642     throws IOException
4706 19 Mar 18 olle 643   {
4706 19 Mar 18 olle 644     float rotationDegrees = 0f;
4706 19 Mar 18 olle 645     importImage2(imageByteArray, x, y, width, height, align, rotationDegrees);
4706 19 Mar 18 olle 646   }
4706 19 Mar 18 olle 647
4706 19 Mar 18 olle 648   /**
4706 19 Mar 18 olle 649     Import an image into the PDF document and place it at the location specified 
4706 19 Mar 18 olle 650     by the x and y coordinates. The image is stretched to fit within the given
4706 19 Mar 18 olle 651     width and height. It can be aligned either to Element.ALIGN_LEFT or
4706 19 Mar 18 olle 652     Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 653     The image is placed in front of existing images.
4706 19 Mar 18 olle 654   */
4706 19 Mar 18 olle 655   public void importImage2(byte[] imageByteArray, float x, float y, float width, float height, int align, float rotationDegrees)
4706 19 Mar 18 olle 656     throws IOException
4706 19 Mar 18 olle 657   {
4706 19 Mar 18 olle 658     try
4706 19 Mar 18 olle 659     {
4706 19 Mar 18 olle 660       Image img = Image.getInstance(imageByteArray);
4706 19 Mar 18 olle 661       importImage2(img, x, y, width, height, align, rotationDegrees);
4706 19 Mar 18 olle 662     }
4706 19 Mar 18 olle 663     catch (DocumentException ex)
4706 19 Mar 18 olle 664     {
4706 19 Mar 18 olle 665       throw new IOException(ex);
4706 19 Mar 18 olle 666     }
4706 19 Mar 18 olle 667   }
4706 19 Mar 18 olle 668
4706 19 Mar 18 olle 669   /**
4706 19 Mar 18 olle 670     Import an image into the PDF document and place it at the location specified 
4706 19 Mar 18 olle 671     by the x and y coordinates. The image is stretched to fit within the given
4706 19 Mar 18 olle 672     width and height. It can be aligned either to Element.ALIGN_LEFT or
4706 19 Mar 18 olle 673     Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 674     The image is placed in front of existing images.
4706 19 Mar 18 olle 675   */
4706 19 Mar 18 olle 676   public void importImage2(Image img, float x, float y, float width, float height, int align)
4706 19 Mar 18 olle 677     throws IOException
4706 19 Mar 18 olle 678   {
4706 19 Mar 18 olle 679     float rotationDegrees = 0f;
4706 19 Mar 18 olle 680     importImage2(img, x, y, width, height, align, rotationDegrees);
4706 19 Mar 18 olle 681   }
4706 19 Mar 18 olle 682
4706 19 Mar 18 olle 683   /**
4706 19 Mar 18 olle 684     Import an image into the PDF document and place it at the location specified 
4706 19 Mar 18 olle 685     by the x and y coordinates. The image is stretched to fit within the given
4706 19 Mar 18 olle 686     width and height. It can be aligned either to Element.ALIGN_LEFT or
4706 19 Mar 18 olle 687     Element.ALIGN_RIGHT and Element.ALIGN_TOP or Element.ALIGN_BOTTOM.
4706 19 Mar 18 olle 688     The image is placed in front of existing images.
4706 19 Mar 18 olle 689   */
4706 19 Mar 18 olle 690   public void importImage2(Image img, float x, float y, float width, float height, int align, float rotationDegrees)
4706 19 Mar 18 olle 691     throws IOException
4706 19 Mar 18 olle 692   {
4706 19 Mar 18 olle 693     try
4706 19 Mar 18 olle 694     {
4706 19 Mar 18 olle 695       if (Float.isNaN(width) && Float.isNaN(height))
4706 19 Mar 18 olle 696       {
4706 19 Mar 18 olle 697         width = img.getWidth();
4706 19 Mar 18 olle 698         height = img.getHeight();
4706 19 Mar 18 olle 699       }
4706 19 Mar 18 olle 700       else if (Float.isNaN(height))
4706 19 Mar 18 olle 701       {
4706 19 Mar 18 olle 702         float scale = width / img.getWidth();
4706 19 Mar 18 olle 703         height = scale * img.getHeight();
4706 19 Mar 18 olle 704       }
4706 19 Mar 18 olle 705       else if (Float.isNaN(width))
4706 19 Mar 18 olle 706       {
4706 19 Mar 18 olle 707         float scale = height / img.getHeight();
4706 19 Mar 18 olle 708         width = scale * img.getWidth();
4706 19 Mar 18 olle 709       }
4706 19 Mar 18 olle 710
4706 19 Mar 18 olle 711       if ((align & Element.ALIGN_RIGHT) > 0)
4706 19 Mar 18 olle 712       {
4706 19 Mar 18 olle 713         x -= width;
4706 19 Mar 18 olle 714       }
4706 19 Mar 18 olle 715       if ((align & Element.ALIGN_TOP) > 0)
4706 19 Mar 18 olle 716       {
4706 19 Mar 18 olle 717         y -= height;
4706 19 Mar 18 olle 718       }
4706 19 Mar 18 olle 719
4706 19 Mar 18 olle 720       img.scaleAbsolute(width, height);
4706 19 Mar 18 olle 721       img.setRotationDegrees(rotationDegrees);
4706 19 Mar 18 olle 722       img.setAbsolutePosition(x, y);
4706 19 Mar 18 olle 723       canvas.addImage(img);
4706 19 Mar 18 olle 724     }
4706 19 Mar 18 olle 725     catch (DocumentException ex)
4706 19 Mar 18 olle 726     {
4706 19 Mar 18 olle 727       throw new IOException(ex);
4706 19 Mar 18 olle 728     }
4706 19 Mar 18 olle 729   }
4706 19 Mar 18 olle 730
4706 19 Mar 18 olle 731 }