2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with the com.oreilly.servlet library, any library
22 * licensed under the Apache Software License, The Sun (tm) Java Advanced
23 * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24 * the above that use the same license as the above), and distribute linked
25 * combinations including the two. You must obey the GNU General Public
26 * License in all respects for all of the code used other than the above
27 * mentioned libraries. If you modify this file, you may extend this exception
28 * to your version of the file, but you are not obligated to do so. If you do
29 * not wish to do so, delete this exception statement from your version.
32 package mircoders.pdf;
34 import mir.log.LoggerWrapper;
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 import java.net.MalformedURLException;
42 import gnu.regexp.REException;
44 import com.lowagie.text.*;
45 import com.lowagie.text.pdf.*;
47 import mir.entity.EntityList;
49 import mircoders.entity.EntityContent;
50 import mircoders.entity.EntityImages;
51 import mircoders.storage.DatabaseContentToMedia;
53 import mir.config.MirPropertiesConfiguration;
54 import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
58 public class PDFGenerator{
60 public Document document;
61 public PdfWriter writer;
62 public PdfContentByte cb;
63 public String localImageDir;
64 public float currentYPosition;
65 public int currentPage;
66 public float pageWidth;
67 public float pageHeight;
68 public float verticalMargin;
69 public float horizontalMargin;
71 public float bottomEdge;
72 public float rightEdge;
73 public float leftEdge;
74 public float footerHeight;
75 public String footerText;
77 protected LoggerWrapper logger;
80 protected MirPropertiesConfiguration configuration;
83 public PDFGenerator(ByteArrayOutputStream out){
84 logger = new LoggerWrapper("PDF.PDFGenerator");
86 configuration = MirPropertiesConfiguration.instance();
88 catch (PropertiesConfigExc e) {
89 throw new RuntimeException("Can't get configuration: " + e.getMessage());
91 localImageDir=configuration.getString("Producer.Image.Path");
93 // step 1: make a document
95 String pageSize = configuration.getString("PDF.Pagesize");
97 if (pageSize.equals("LETTER")){
98 document = new Document(PageSize.LETTER);
103 document = new Document(PageSize.A4);
111 horizontalMargin = 20;
115 topEdge=pageHeight-verticalMargin;
116 bottomEdge=verticalMargin;
117 rightEdge=pageWidth-horizontalMargin;
118 leftEdge=horizontalMargin;
120 currentYPosition=topEdge;
123 String headerText = configuration.getString("PDF.Title");
124 footerText = configuration.getString("PDF.Footer");
126 writer = PdfWriter.getInstance(document, out);
127 cb = writer.getDirectContent();
133 ColumnText ct = new ColumnText(cb);
135 ct.addText(new Phrase(headerText, FontFactory.getFont(FontFactory.COURIER, 24,Font.BOLD)));
137 float[] rightCol = {rightEdge,topEdge,rightEdge,topEdge-28};
138 float[] leftCol = {leftEdge,topEdge,leftEdge,topEdge-28};
139 // int status = ct.go();
140 ct.setColumns(leftCol,rightCol);
141 // int status=ct.go();
142 ct.setYLine(topEdge);
143 ct.setAlignment(Element.ALIGN_CENTER);
146 currentYPosition = currentYPosition - 28;
149 catch(DocumentException de) {
150 logger.error(de.getMessage());
159 public void addIndexItem(EntityContent entityContent){
161 float indexLineHeight = 16;
162 ColumnText ict = new ColumnText(cb);
163 String theTitle = entityContent.getValue("title");
164 String theCreator = entityContent.getValue("creator");
165 Phrase titleP=new Phrase(" - " + theTitle,new Font(Font.HELVETICA,12,Font.BOLD));
166 Phrase creatorP=new Phrase( " :: " + theCreator,new Font(Font.HELVETICA,12));
167 float toYPosition = currentYPosition - indexLineHeight;
168 float[] leftIndexCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
169 float[] rightIndexCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
171 ict.addText(creatorP);
172 ict.setColumns(leftIndexCols,rightIndexCols);
173 ict.setYLine(currentYPosition);
174 ict.setAlignment(Element.ALIGN_LEFT);
176 currentYPosition = toYPosition;
178 catch(DocumentException de) {
179 logger.error(de.getMessage());
187 public void addLine(){
189 cb.moveTo(rightEdge, currentYPosition-5);
190 cb.lineTo(leftEdge, currentYPosition-5);
192 currentYPosition = currentYPosition - 10;
196 public void addFooter(){
198 ColumnText fct = new ColumnText(cb);
200 cb.moveTo(rightEdge, bottomEdge+footerHeight-5);
201 cb.lineTo(leftEdge, bottomEdge+footerHeight-5);
203 float[] leftFooterCols = {leftEdge,bottomEdge+footerHeight-1,leftEdge,bottomEdge};
204 float[] rightFooterCols = {rightEdge,bottomEdge+footerHeight-1,rightEdge,bottomEdge};
206 Paragraph footerP=new Paragraph(footerText,new Font(Font.HELVETICA,12));
207 fct.addText(footerP);
209 fct.setColumns(leftFooterCols,rightFooterCols);
210 fct.setYLine(bottomEdge+footerHeight-1);
211 fct.setAlignment(Element.ALIGN_JUSTIFIED);
214 Paragraph numberP=new Paragraph((new Integer(currentPage)).toString(),new Font(Font.HELVETICA,12,Font.BOLD));
215 fct.addText(numberP);
216 fct.setAlignment(Element.ALIGN_RIGHT);
220 catch (DocumentException de){
221 logger.error(de.getMessage());
227 public void newPage(){
233 currentYPosition=topEdge;
235 catch(DocumentException de) {
236 logger.error(de.getMessage());
240 public boolean enoughY(int heightOfBlockToAdd){
241 if ((currentYPosition - heightOfBlockToAdd - footerHeight) < bottomEdge )
248 public void add(EntityContent entityContent){
249 logger.error("adding a content Entity");
250 EntityList images=DatabaseContentToMedia.getInstance().getImages(entityContent);
251 String theTitle = entityContent.getValue("title");
252 String theCreator = entityContent.getValue("creator");
253 String theDate = entityContent.getValue("webdb_create_formatted");
254 String theDescriptionRaw = entityContent.getValue("description");
255 String theContentRaw = entityContent.getValue("content_data");
256 String theSource = configuration.getString("Producer.ProductionHost") + "/" + configuration.getString("StandardLanguage") + entityContent.getValue("publish_path") + entityContent.getValue("id") + ".shtml";
258 boolean addImageOnLeft = true;
260 String theContent = "";
261 String theDescription = "";
264 RE re1 = new RE("\r?\n\r?\n");
265 String theContent1 = re1.substituteAll(theContentRaw,"BREAKHERE");
266 String theDescription1 = re1.substituteAll(theDescriptionRaw,"BREAKHERE");
268 RE re2 = new RE("\r?\n");
269 String theContent2 = re2.substituteAll(theContent1," ");
270 String theDescription2 = re2.substituteAll(theDescription1," ");
272 RE re3 = new RE("BREAKHERE");
273 theContent = " " + re3.substituteAll(theContent2,"\n ");
274 theDescription = re3.substituteAll(theDescription2,"\n ");
277 catch(REException ree){
278 logger.error(ree.getMessage());
284 // make a line (don't worry about the bottomEdge, we should actually write in that area(it's a thin line!)
286 cb.moveTo(rightEdge, currentYPosition-5);
287 cb.lineTo(leftEdge, currentYPosition-5);
290 currentYPosition = currentYPosition - 10;
293 //see if we have room for the author and title
298 ColumnText ct = new ColumnText(cb);
300 Paragraph titleP=new Paragraph(theTitle+"\n",new Font(Font.HELVETICA,14,Font.BOLD));
301 Paragraph whowhenP=new Paragraph(theCreator + " " + theDate ,new Font(Font.HELVETICA,14));
303 ct.addText(whowhenP);
305 ct.setYLine(currentYPosition);
306 ct.setAlignment(Element.ALIGN_LEFT);
308 float toYPosition = currentYPosition - 36;
309 float[] leftHeadCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
310 float[] rightHeadCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
312 ct.setColumns(leftHeadCols,rightHeadCols);
314 currentYPosition = toYPosition;
317 // Now add the description, one line at a time, the ct should be empty at this point
319 Paragraph descP=new Paragraph(theDescription,new Font(Font.HELVETICA,12,Font.BOLD));
323 // every article has a description, so we can assume that:
324 int status = ColumnText.NO_MORE_COLUMN;
326 int descriptionLineHeight=16;
328 while ((status & ColumnText.NO_MORE_TEXT) == 0){
329 //there is still text left in the description.
330 logger.error("adding a line to the description");
332 //but is there room on the page?
333 if (! enoughY(descriptionLineHeight)){
337 //now we are set to add a line of descriptive text
338 toYPosition = currentYPosition - descriptionLineHeight;
339 float[] leftDescCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
340 float[] rightDescCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
341 ct.setColumns(leftDescCols,rightDescCols);
342 ct.setYLine(currentYPosition);
343 ct.setAlignment(Element.ALIGN_JUSTIFIED);
345 currentYPosition = toYPosition;
348 // ok, now on to the meat of the job ahead
350 int contentLineHeight=16;
352 //let's go ahead and add in all the body text
353 Paragraph contentP=new Paragraph(theContent,new Font(Font.HELVETICA,10));
354 ct.addText(contentP);
355 //and assume we have at least one line of text in the content
356 status = ColumnText.NO_MORE_COLUMN;
358 int maxImageHeight=250;
359 int maxImageWidth=250;
362 // let's add a little bit of text, like a couple of lines
364 while (((status & ColumnText.NO_MORE_TEXT) == 0) && x<3){
365 //in case we have some text left
367 logger.error("adding a line to the content");
369 //but is there room on the page?
370 if (! enoughY(contentLineHeight)){
374 //now we are set to add a line of content text
375 toYPosition = currentYPosition - contentLineHeight;
376 float[] leftContentCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
377 float[] rightContentCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
378 ct.setColumns(leftContentCols,rightContentCols);
379 ct.setYLine(currentYPosition);
380 ct.setAlignment(Element.ALIGN_JUSTIFIED);
382 currentYPosition = toYPosition;
388 while (images.hasNext()){
390 EntityImages currentImage=(EntityImages) images.next();
391 float img_width=(new Float(currentImage.getValue("img_width"))).floatValue();
392 float img_height=(new Float(currentImage.getValue("img_height"))).floatValue();
393 if (img_height>maxImageHeight){
394 img_width=(new Float((new Float(img_width*(maxImageHeight/img_height))).intValue())).floatValue();
395 img_height=maxImageHeight;
397 if (img_width>maxImageWidth){
398 img_height=(new Float((new Float(img_height*(maxImageWidth/img_width))).intValue())).floatValue();
399 img_width=maxImageWidth;
402 String img_title=currentImage.getValue("title");
403 String img_path=currentImage.getValue("publish_path");
408 if ((status & ColumnText.NO_MORE_TEXT) == 0){
409 // there is still text, so add an image which will have text wrapped around it, then add the text which
410 // will be on the left or the right of the image
412 float templateMinimumHeight = img_height+20;
413 float templateWidth = img_width+10;
415 float templateHeight = templateMinimumHeight+contentLineHeight-(templateMinimumHeight % contentLineHeight);
418 PdfTemplate template = cb.createTemplate(templateWidth,templateHeight);
421 //here we need a page check
422 if (! enoughY((new Float(templateHeight)).intValue())){
423 //ok, well just fill text to the bottom then
424 toYPosition = bottomEdge+footerHeight;
425 float[] leftBottomCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
426 float[] rightBottomCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
427 ct.setColumns(leftBottomCols,rightBottomCols);
428 ct.setYLine(currentYPosition);
429 ct.setAlignment(Element.ALIGN_JUSTIFIED);
434 toYPosition=currentYPosition - templateHeight;
436 Image theImage = Image.getInstance(localImageDir+img_path);
437 theImage.scaleAbsolute(img_width,img_height);
438 theImage.setAbsolutePosition(5,13);
439 template.addImage(theImage);
440 template.beginText();
441 BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
442 template.setFontAndSize(bf, 8);
443 template.setTextMatrix(5, 3);
444 template.showText(img_title);
448 float leftImageTextEdge=leftEdge;
449 float rightImageTextEdge=rightEdge;
453 cb.addTemplate(template,leftEdge,toYPosition);
454 leftImageTextEdge=leftEdge+templateWidth+5;
455 addImageOnLeft = false;
458 cb.addTemplate(template,rightEdge-templateWidth,toYPosition);
459 rightImageTextEdge = rightEdge-templateWidth-5;
460 addImageOnLeft = true;
463 logger.error("adding template at " + leftEdge + "," + toYPosition);
465 //and fill some text while we are at it
467 float[] leftBottomCols = {leftImageTextEdge,currentYPosition,leftImageTextEdge,toYPosition};
468 float[] rightBottomCols = {rightImageTextEdge,currentYPosition,rightImageTextEdge,toYPosition};
469 ct.setColumns(leftBottomCols,rightBottomCols);
470 ct.setYLine(currentYPosition);
471 ct.setAlignment(Element.ALIGN_JUSTIFIED);
474 currentYPosition=toYPosition;
479 //add an image on the left with a big caption to the right
480 currentYPosition = currentYPosition - 10;
481 float templateMinimumHeight = img_height;
482 float templateWidth = img_width;
483 float templateHeight = templateMinimumHeight+contentLineHeight-(templateMinimumHeight % contentLineHeight);
484 PdfTemplate template = cb.createTemplate(templateWidth,templateHeight);
485 if (! enoughY((new Float(templateHeight)).intValue())){
488 toYPosition=currentYPosition - templateHeight;
489 Image theImage = Image.getInstance(localImageDir+img_path);
490 theImage.setAbsolutePosition(0,13);
491 theImage.scaleAbsolute(img_width,img_height);
492 template.addImage(theImage);
494 cb.addTemplate(template,leftEdge,toYPosition);
497 ColumnText cct = new ColumnText(cb);
498 float[] leftCaptionCols = {leftEdge+templateWidth+5,currentYPosition-5,leftEdge+templateWidth+5,toYPosition};
499 float[] rightCaptionCols = {rightEdge,currentYPosition-5,rightEdge,toYPosition};
501 Paragraph captionP=new Paragraph(img_title,new Font(Font.HELVETICA,16,Font.BOLD));
502 cct.addText(captionP);
503 cct.setColumns(leftCaptionCols,rightCaptionCols);
504 cct.setYLine(currentYPosition-5);
505 cct.setAlignment(Element.ALIGN_LEFT);
510 currentYPosition=toYPosition;
518 while ((status & ColumnText.NO_MORE_TEXT) == 0){
519 //in case we have some text left
521 logger.error("adding a line to the content");
523 //but is there room on the page?
524 if (! enoughY(contentLineHeight)){
528 //now we are set to add a line of content text
529 toYPosition = currentYPosition - contentLineHeight;
530 float[] leftContentCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
531 float[] rightContentCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
532 ct.setColumns(leftContentCols,rightContentCols);
533 ct.setYLine(currentYPosition);
534 ct.setAlignment(Element.ALIGN_JUSTIFIED);
536 currentYPosition = toYPosition;
540 // and add the source link
542 toYPosition = currentYPosition - contentLineHeight;
543 float[] leftSourceCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
544 float[] rightSourceCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
545 ct.setColumns(leftSourceCols,rightSourceCols);
546 Paragraph sourceP = new Paragraph(theSource,new Font(Font.COURIER,12,Font.BOLD));
548 ct.setYLine(currentYPosition);
549 ct.setAlignment(Element.ALIGN_RIGHT);
551 currentYPosition = toYPosition;
558 catch(DocumentException de) {
559 logger.error(de.getMessage());
561 catch(MalformedURLException de) {
562 logger.error(de.getMessage());
564 catch(IOException de) {
565 logger.error(de.getMessage());
567 /* while(images.hasNext()){
569 EntityImages currentImage=(EntityImages) images.next();
570 float img_width=(new Float(currentImage.getValue("img_width"))).floatValue();
571 float img_height=(new Float(currentImage.getValue("img_height"))).floatValue();
573 img_height=(new Float((new Float(img_height*(250.0F/img_width))).intValue())).floatValue();
576 String img_title=currentImage.getValue("title");
577 String img_path=currentImage.getValue("publish_path");
579 PdfTemplate template = cb.createTemplate(img_width+10, img_height+20);
581 Image theImage = Image.getInstance(localImageDir+img_path);
582 theImage.setAbsolutePosition(5,13);
583 template.addImage(theImage);
584 template.beginText();
585 BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
586 template.setFontAndSize(bf, 8);
587 template.setTextMatrix(5, 3);
588 template.showText(img_title);
590 ImgTemplate it = new ImgTemplate(template);
591 it.setAlignment(Image.RIGHT | Image.TEXTWRAP);
594 document.add(new Paragraph("this is a test of adding some text to see if we bump down a line when there is some text"));
597 catch(DocumentException de) {
598 System.err.println(de.getMessage());
600 catch(IOException ioe) {
601 System.err.println(ioe.getMessage());
609 Paragraph p=new Paragraph(theContent,new Font(Font.HELVETICA,11));
610 p.setAlignment(Paragraph.ALIGN_JUSTIFIED);
614 catch(DocumentException de) {
615 System.err.println(de.getMessage());