--- /dev/null
+/*
+ * Copyright (C) 2001, 2002 The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mir; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * In addition, as a special exception, The Mir-coders gives permission to link
+ * the code of this program with the com.oreilly.servlet library, any library
+ * licensed under the Apache Software License, The Sun (tm) Java Advanced
+ * Imaging library (JAI), The Sun JIMI library (or with modified versions of
+ * the above that use the same license as the above), and distribute linked
+ * combinations including the two. You must obey the GNU General Public
+ * License in all respects for all of the code used other than the above
+ * mentioned libraries. If you modify this file, you may extend this exception
+ * to your version of the file, but you are not obligated to do so. If you do
+ * not wish to do so, delete this exception statement from your version.
+ */
+
+package mircoders.pdf;
+
+import mir.log.LoggerWrapper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+
+import gnu.regexp.RE;
+import gnu.regexp.REException;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+
+import mir.entity.EntityList;
+
+import mircoders.entity.EntityContent;
+import mircoders.entity.EntityImages;
+import mircoders.storage.DatabaseContentToMedia;
+
+import mir.config.MirPropertiesConfiguration;
+import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
+
+
+
+public class PDFGenerator{
+
+ public Document document;
+ public PdfWriter writer;
+ public PdfContentByte cb;
+ public String localImageDir;
+ public float currentYPosition;
+ public int currentPage;
+ public float pageWidth;
+ public float pageHeight;
+ public float verticalMargin;
+ public float horizontalMargin;
+ public float topEdge;
+ public float bottomEdge;
+ public float rightEdge;
+ public float leftEdge;
+ public float footerHeight;
+ public String footerText;
+
+ protected LoggerWrapper logger;
+
+
+ protected MirPropertiesConfiguration configuration;
+
+
+ public PDFGenerator(ByteArrayOutputStream out){
+ logger = new LoggerWrapper("PDF.PDFGenerator");
+ try {
+ configuration = MirPropertiesConfiguration.instance();
+ }
+ catch (PropertiesConfigExc e) {
+ throw new RuntimeException("Can't get configuration: " + e.getMessage());
+ }
+ localImageDir=configuration.getString("Producer.Image.Path");
+
+ // step 1: make a document
+
+ String pageSize = configuration.getString("PDF.Pagesize");
+
+ if (pageSize.equals("LETTER")){
+ document = new Document(PageSize.LETTER);
+ pageWidth = 612;
+ pageHeight = 792;
+ }
+ else {
+ document = new Document(PageSize.A4);
+ pageWidth=595;
+ pageHeight=842;
+ }
+
+ try {
+
+ verticalMargin = 20;
+ horizontalMargin = 20;
+
+ footerHeight = 54;
+
+ topEdge=pageHeight-verticalMargin;
+ bottomEdge=verticalMargin;
+ rightEdge=pageWidth-horizontalMargin;
+ leftEdge=horizontalMargin;
+
+ currentYPosition=topEdge;
+ currentPage = 1;
+
+ String headerText = configuration.getString("PDF.Title");
+ footerText = configuration.getString("PDF.Footer");
+
+ writer = PdfWriter.getInstance(document, out);
+ cb = writer.getDirectContent();
+
+ document.open();
+
+
+
+ ColumnText ct = new ColumnText(cb);
+ //add a basic header
+ ct.addText(new Phrase(headerText, FontFactory.getFont(FontFactory.COURIER, 24,Font.BOLD)));
+
+ float[] rightCol = {rightEdge,topEdge,rightEdge,topEdge-28};
+ float[] leftCol = {leftEdge,topEdge,leftEdge,topEdge-28};
+ // int status = ct.go();
+ ct.setColumns(leftCol,rightCol);
+ // int status=ct.go();
+ ct.setYLine(topEdge);
+ ct.setAlignment(Element.ALIGN_CENTER);
+ ct.go();
+
+ currentYPosition = currentYPosition - 28;
+
+ }
+ catch(DocumentException de) {
+ logger.error(de.getMessage());
+ }
+ }
+
+ public void stop(){
+ addFooter();
+ document.close();
+ }
+
+ public void addIndexItem(EntityContent entityContent){
+ try {
+ float indexLineHeight = 16;
+ ColumnText ict = new ColumnText(cb);
+ String theTitle = entityContent.getValue("title");
+ String theCreator = entityContent.getValue("creator");
+ Phrase titleP=new Phrase(" - " + theTitle,new Font(Font.HELVETICA,12,Font.BOLD));
+ Phrase creatorP=new Phrase( " :: " + theCreator,new Font(Font.HELVETICA,12));
+ float toYPosition = currentYPosition - indexLineHeight;
+ float[] leftIndexCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightIndexCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+ ict.addText(titleP);
+ ict.addText(creatorP);
+ ict.setColumns(leftIndexCols,rightIndexCols);
+ ict.setYLine(currentYPosition);
+ ict.setAlignment(Element.ALIGN_LEFT);
+ int status=ict.go();
+ currentYPosition = toYPosition;
+ }
+ catch(DocumentException de) {
+ logger.error(de.getMessage());
+ }
+
+
+
+ }
+
+
+ public void addLine(){
+ cb.setLineWidth(1f);
+ cb.moveTo(rightEdge, currentYPosition-5);
+ cb.lineTo(leftEdge, currentYPosition-5);
+ cb.stroke();
+ currentYPosition = currentYPosition - 10;
+
+ }
+
+ public void addFooter(){
+ try{
+ ColumnText fct = new ColumnText(cb);
+ cb.setLineWidth(1f);
+ cb.moveTo(rightEdge, bottomEdge+footerHeight-5);
+ cb.lineTo(leftEdge, bottomEdge+footerHeight-5);
+ cb.stroke();
+ float[] leftFooterCols = {leftEdge,bottomEdge+footerHeight-1,leftEdge,bottomEdge};
+ float[] rightFooterCols = {rightEdge,bottomEdge+footerHeight-1,rightEdge,bottomEdge};
+
+ Paragraph footerP=new Paragraph(footerText,new Font(Font.HELVETICA,12));
+ fct.addText(footerP);
+
+ fct.setColumns(leftFooterCols,rightFooterCols);
+ fct.setYLine(bottomEdge+footerHeight-1);
+ fct.setAlignment(Element.ALIGN_JUSTIFIED);
+ int status=fct.go();
+
+ Paragraph numberP=new Paragraph((new Integer(currentPage)).toString(),new Font(Font.HELVETICA,12,Font.BOLD));
+ fct.addText(numberP);
+ fct.setAlignment(Element.ALIGN_RIGHT);
+ status=fct.go();
+
+ }
+ catch (DocumentException de){
+ logger.error(de.getMessage());
+ }
+
+
+ }
+
+ public void newPage(){
+ try{
+ //add a footer
+ addFooter();
+ document.newPage();
+ currentPage++;
+ currentYPosition=topEdge;
+ }
+ catch(DocumentException de) {
+ logger.error(de.getMessage());
+ }
+ }
+
+ public boolean enoughY(int heightOfBlockToAdd){
+ if ((currentYPosition - heightOfBlockToAdd - footerHeight) < bottomEdge )
+ return false;
+ else
+ return true;
+ }
+
+
+ public void add(EntityContent entityContent){
+ logger.error("adding a content Entity");
+ EntityList images=DatabaseContentToMedia.getInstance().getImages(entityContent);
+ String theTitle = entityContent.getValue("title");
+ String theCreator = entityContent.getValue("creator");
+ String theDate = entityContent.getValue("webdb_create_formatted");
+ String theDescriptionRaw = entityContent.getValue("description");
+ String theContentRaw = entityContent.getValue("content_data");
+ String theSource = configuration.getString("Producer.ProductionHost") + "/" + configuration.getString("StandardLanguage") + entityContent.getValue("publish_path") + entityContent.getValue("id") + ".shtml";
+
+ boolean addImageOnLeft = true;
+
+ String theContent = "";
+ String theDescription = "";
+
+ try {
+ RE re1 = new RE("\r?\n\r?\n");
+ String theContent1 = re1.substituteAll(theContentRaw,"BREAKHERE");
+ String theDescription1 = re1.substituteAll(theDescriptionRaw,"BREAKHERE");
+
+ RE re2 = new RE("\r?\n");
+ String theContent2 = re2.substituteAll(theContent1," ");
+ String theDescription2 = re2.substituteAll(theDescription1," ");
+
+ RE re3 = new RE("BREAKHERE");
+ theContent = " " + re3.substituteAll(theContent2,"\n ");
+ theDescription = re3.substituteAll(theDescription2,"\n ");
+
+ }
+ catch(REException ree){
+ logger.error(ree.getMessage());
+ }
+
+
+ try {
+
+ // make a line (don't worry about the bottomEdge, we should actually write in that area(it's a thin line!)
+ cb.setLineWidth(1f);
+ cb.moveTo(rightEdge, currentYPosition-5);
+ cb.lineTo(leftEdge, currentYPosition-5);
+ cb.stroke();
+
+ currentYPosition = currentYPosition - 10;
+
+
+ //see if we have room for the author and title
+ if (! enoughY(36)){
+ newPage();
+ }
+
+ ColumnText ct = new ColumnText(cb);
+
+ Paragraph titleP=new Paragraph(theTitle+"\n",new Font(Font.HELVETICA,14,Font.BOLD));
+ Paragraph whowhenP=new Paragraph(theCreator + " " + theDate ,new Font(Font.HELVETICA,14));
+ ct.addText(titleP);
+ ct.addText(whowhenP);
+
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_LEFT);
+
+ float toYPosition = currentYPosition - 36;
+ float[] leftHeadCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightHeadCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+
+ ct.setColumns(leftHeadCols,rightHeadCols);
+ ct.go();
+ currentYPosition = toYPosition;
+
+
+ // Now add the description, one line at a time, the ct should be empty at this point
+
+ Paragraph descP=new Paragraph(theDescription,new Font(Font.HELVETICA,12,Font.BOLD));
+
+ ct.addText(descP);
+
+ // every article has a description, so we can assume that:
+ int status = ColumnText.NO_MORE_COLUMN;
+
+ int descriptionLineHeight=16;
+
+ while ((status & ColumnText.NO_MORE_TEXT) == 0){
+ //there is still text left in the description.
+ logger.error("adding a line to the description");
+
+ //but is there room on the page?
+ if (! enoughY(descriptionLineHeight)){
+ newPage();
+ }
+
+ //now we are set to add a line of descriptive text
+ toYPosition = currentYPosition - descriptionLineHeight;
+ float[] leftDescCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightDescCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+ ct.setColumns(leftDescCols,rightDescCols);
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_JUSTIFIED);
+ status=ct.go();
+ currentYPosition = toYPosition;
+ }
+
+ // ok, now on to the meat of the job ahead
+
+ int contentLineHeight=16;
+
+ //let's go ahead and add in all the body text
+ Paragraph contentP=new Paragraph(theContent,new Font(Font.HELVETICA,10));
+ ct.addText(contentP);
+ //and assume we have at least one line of text in the content
+ status = ColumnText.NO_MORE_COLUMN;
+
+ int maxImageHeight=250;
+ int maxImageWidth=250;
+
+
+ // let's add a little bit of text, like a couple of lines
+ int x = 0;
+ while (((status & ColumnText.NO_MORE_TEXT) == 0) && x<3){
+ //in case we have some text left
+
+ logger.error("adding a line to the content");
+
+ //but is there room on the page?
+ if (! enoughY(contentLineHeight)){
+ newPage();
+ }
+
+ //now we are set to add a line of content text
+ toYPosition = currentYPosition - contentLineHeight;
+ float[] leftContentCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightContentCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+ ct.setColumns(leftContentCols,rightContentCols);
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_JUSTIFIED);
+ status=ct.go();
+ currentYPosition = toYPosition;
+ x++;
+ }
+
+
+
+ while (images.hasNext()){
+
+ EntityImages currentImage=(EntityImages) images.next();
+ float img_width=(new Float(currentImage.getValue("img_width"))).floatValue();
+ float img_height=(new Float(currentImage.getValue("img_height"))).floatValue();
+ if (img_height>maxImageHeight){
+ img_width=(new Float((new Float(img_width*(maxImageHeight/img_height))).intValue())).floatValue();
+ img_height=maxImageHeight;
+ }
+ if (img_width>maxImageWidth){
+ img_height=(new Float((new Float(img_height*(maxImageWidth/img_width))).intValue())).floatValue();
+ img_width=maxImageWidth;
+ }
+
+ String img_title=currentImage.getValue("title");
+ String img_path=currentImage.getValue("publish_path");
+
+
+
+
+ if ((status & ColumnText.NO_MORE_TEXT) == 0){
+ // there is still text, so add an image which will have text wrapped around it, then add the text which
+ // will be on the left or the right of the image
+
+ float templateMinimumHeight = img_height+20;
+ float templateWidth = img_width+10;
+
+ float templateHeight = templateMinimumHeight+contentLineHeight-(templateMinimumHeight % contentLineHeight);
+
+
+ PdfTemplate template = cb.createTemplate(templateWidth,templateHeight);
+
+
+ //here we need a page check
+ if (! enoughY((new Float(templateHeight)).intValue())){
+ //ok, well just fill text to the bottom then
+ toYPosition = bottomEdge+footerHeight;
+ float[] leftBottomCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightBottomCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+ ct.setColumns(leftBottomCols,rightBottomCols);
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_JUSTIFIED);
+ status=ct.go();
+ newPage();
+ }
+
+ toYPosition=currentYPosition - templateHeight;
+
+ Image theImage = Image.getInstance(localImageDir+img_path);
+ theImage.scaleAbsolute(img_width,img_height);
+ theImage.setAbsolutePosition(5,13);
+ template.addImage(theImage);
+ template.beginText();
+ BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
+ template.setFontAndSize(bf, 8);
+ template.setTextMatrix(5, 3);
+ template.showText(img_title);
+ template.endText();
+
+
+ float leftImageTextEdge=leftEdge;
+ float rightImageTextEdge=rightEdge;
+
+
+ if (addImageOnLeft){
+ cb.addTemplate(template,leftEdge,toYPosition);
+ leftImageTextEdge=leftEdge+templateWidth+5;
+ addImageOnLeft = false;
+ }
+ else {
+ cb.addTemplate(template,rightEdge-templateWidth,toYPosition);
+ rightImageTextEdge = rightEdge-templateWidth-5;
+ addImageOnLeft = true;
+ }
+
+ logger.error("adding template at " + leftEdge + "," + toYPosition);
+
+ //and fill some text while we are at it
+
+ float[] leftBottomCols = {leftImageTextEdge,currentYPosition,leftImageTextEdge,toYPosition};
+ float[] rightBottomCols = {rightImageTextEdge,currentYPosition,rightImageTextEdge,toYPosition};
+ ct.setColumns(leftBottomCols,rightBottomCols);
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_JUSTIFIED);
+ status=ct.go();
+
+ currentYPosition=toYPosition;
+
+
+ }
+ else {
+ //add an image on the left with a big caption to the right
+ currentYPosition = currentYPosition - 10;
+ float templateMinimumHeight = img_height;
+ float templateWidth = img_width;
+ float templateHeight = templateMinimumHeight+contentLineHeight-(templateMinimumHeight % contentLineHeight);
+ PdfTemplate template = cb.createTemplate(templateWidth,templateHeight);
+ if (! enoughY((new Float(templateHeight)).intValue())){
+ newPage();
+ }
+ toYPosition=currentYPosition - templateHeight;
+ Image theImage = Image.getInstance(localImageDir+img_path);
+ theImage.setAbsolutePosition(0,13);
+ theImage.scaleAbsolute(img_width,img_height);
+ template.addImage(theImage);
+
+ cb.addTemplate(template,leftEdge,toYPosition);
+
+ // add a big caption
+ ColumnText cct = new ColumnText(cb);
+ float[] leftCaptionCols = {leftEdge+templateWidth+5,currentYPosition-5,leftEdge+templateWidth+5,toYPosition};
+ float[] rightCaptionCols = {rightEdge,currentYPosition-5,rightEdge,toYPosition};
+
+ Paragraph captionP=new Paragraph(img_title,new Font(Font.HELVETICA,16,Font.BOLD));
+ cct.addText(captionP);
+ cct.setColumns(leftCaptionCols,rightCaptionCols);
+ cct.setYLine(currentYPosition-5);
+ cct.setAlignment(Element.ALIGN_LEFT);
+ cct.go();
+
+
+
+ currentYPosition=toYPosition;
+
+
+ }
+
+ }
+
+
+ while ((status & ColumnText.NO_MORE_TEXT) == 0){
+ //in case we have some text left
+
+ logger.error("adding a line to the content");
+
+ //but is there room on the page?
+ if (! enoughY(contentLineHeight)){
+ newPage();
+ }
+
+ //now we are set to add a line of content text
+ toYPosition = currentYPosition - contentLineHeight;
+ float[] leftContentCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightContentCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+ ct.setColumns(leftContentCols,rightContentCols);
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_JUSTIFIED);
+ status=ct.go();
+ currentYPosition = toYPosition;
+
+ }
+
+ // and add the source link
+
+ toYPosition = currentYPosition - contentLineHeight;
+ float[] leftSourceCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+ float[] rightSourceCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+ ct.setColumns(leftSourceCols,rightSourceCols);
+ Paragraph sourceP = new Paragraph(theSource,new Font(Font.COURIER,12,Font.BOLD));
+ ct.addText(sourceP);
+ ct.setYLine(currentYPosition);
+ ct.setAlignment(Element.ALIGN_RIGHT);
+ status=ct.go();
+ currentYPosition = toYPosition;
+
+
+
+
+
+ }
+ catch(DocumentException de) {
+ logger.error(de.getMessage());
+ }
+ catch(MalformedURLException de) {
+ logger.error(de.getMessage());
+ }
+ catch(IOException de) {
+ logger.error(de.getMessage());
+ }
+ /* while(images.hasNext()){
+
+ EntityImages currentImage=(EntityImages) images.next();
+ float img_width=(new Float(currentImage.getValue("img_width"))).floatValue();
+ float img_height=(new Float(currentImage.getValue("img_height"))).floatValue();
+ if (img_width>250){
+ img_height=(new Float((new Float(img_height*(250.0F/img_width))).intValue())).floatValue();
+ img_width=250.0F;
+ }
+ String img_title=currentImage.getValue("title");
+ String img_path=currentImage.getValue("publish_path");
+
+ PdfTemplate template = cb.createTemplate(img_width+10, img_height+20);
+ try{
+ Image theImage = Image.getInstance(localImageDir+img_path);
+ theImage.setAbsolutePosition(5,13);
+ template.addImage(theImage);
+ template.beginText();
+ BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
+ template.setFontAndSize(bf, 8);
+ template.setTextMatrix(5, 3);
+ template.showText(img_title);
+ template.endText();
+ ImgTemplate it = new ImgTemplate(template);
+ it.setAlignment(Image.RIGHT | Image.TEXTWRAP);
+ document.add(it);
+
+ 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"));
+
+ }
+ catch(DocumentException de) {
+ System.err.println(de.getMessage());
+ }
+ catch(IOException ioe) {
+ System.err.println(ioe.getMessage());
+ }
+ } */
+
+ /*
+ try {
+
+
+ Paragraph p=new Paragraph(theContent,new Font(Font.HELVETICA,11));
+ p.setAlignment(Paragraph.ALIGN_JUSTIFIED);
+
+ document.add(p);
+ }
+ catch(DocumentException de) {
+ System.err.println(de.getMessage());
+ }
+
+ */
+
+ }
+
+}
+
+