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 any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
30 package mircoders.pdf;
32 import com.lowagie.text.*;
33 import com.lowagie.text.pdf.*;
34 import mir.config.MirPropertiesConfiguration;
35 import mir.entity.EntityBrowser;
36 import mir.entity.adapter.EntityAdapter;
37 import mir.generator.GeneratorExc;
38 import mir.generator.GeneratorHelper;
39 import mir.log.LoggerWrapper;
40 import mir.misc.StringUtil;
41 import mir.util.DateTimeRoutines;
42 import mir.util.HTMLRoutines;
43 import mir.util.ParameterExpander;
44 import mircoders.entity.EntityContent;
45 import mircoders.entity.EntityImages;
46 import mircoders.global.MirGlobal;
47 import mircoders.localizer.MirLocalizerExc;
48 import mircoders.storage.DatabaseImages;
49 import multex.Failure;
50 import org.apache.oro.text.regex.*;
52 import java.io.ByteArrayOutputStream;
53 import java.io.IOException;
54 import java.net.MalformedURLException;
56 import java.util.List;
58 public class PDFGenerator {
59 public Document document;
60 public PdfWriter writer;
61 public PdfContentByte cb;
62 public String localImageDir;
63 public float currentYPosition;
64 public int currentPage;
65 public float pageWidth;
66 public float pageHeight;
67 public float verticalMargin;
68 public float horizontalMargin;
70 public float bottomEdge;
71 public float rightEdge;
72 public float leftEdge;
74 public int maxImageHeight;
75 public int maxImageWidth;
76 protected LoggerWrapper logger;
78 public int indexFontSize;
79 public int indexLineHeight;
80 public int indexFontFamily;
82 public float footerHeight;
83 public String footerText;
84 public int footerFontSize;
85 public int footerFontFamily;
87 public int metaHeight;
88 public int metaFontSize;
89 public int metaFontFamily;
91 public int descriptionLineHeight;
92 public int descriptionFontSize;
93 public int descriptionFontFamily;
95 public int contentLineHeight;
96 public int contentFontSize;
97 public int contentFontFamily;
99 public int sourceLineHeight;
100 public int sourceFontSize;
101 public int sourceFontFamily;
103 public int bigImageCaptionFontSize;
104 public int bigImageCaptionFontFamily;
106 protected MirPropertiesConfiguration configuration;
107 private static Pattern nobackslashr;
108 private static Pattern HxTag;
109 private static Pattern ListItemTag;
110 private static Pattern ListTag;
111 private static Pattern DivTag;
112 private static Pattern PTag;
113 private static Pattern PTagClose;
114 private static Pattern BRTag;
115 private static Pattern ATagAll;
116 private static Pattern noTags;
117 private static Pattern re1;
118 private static Pattern re2;
119 private static Pattern re3;
122 Perl5Compiler compiler = new Perl5Compiler();
125 Pattern nobackslashr = compiler.compile("\r");
127 HxTag = compiler.compile("</?h[1-6][^>]*>", Perl5Compiler.READ_ONLY_MASK +
128 Perl5Compiler.CASE_INSENSITIVE_MASK );
129 ListItemTag = compiler.compile("<li[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK);
130 ListTag = compiler.compile("<(u|o)l[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK);
131 DivTag = compiler.compile("</?div[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK);
132 PTag = compiler.compile("<(p|P)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK);
133 PTagClose = compiler.compile("</(p|P)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK);
134 BRTag = compiler.compile("<(br|BR)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK);
135 ATagAll = compiler.compile("<a[^>]*href=(?:\"|\')([^#\"\'][^\'\"]+)(?:\"|\')[^>]*>(.*?)</a>",
136 Perl5Compiler.READ_ONLY_MASK +
137 Perl5Compiler.CASE_INSENSITIVE_MASK );
138 noTags = compiler.compile("<[^>]*>", Perl5Compiler.READ_ONLY_MASK);
139 re1 = compiler.compile("\r?\n\r?\n", Perl5Compiler.READ_ONLY_MASK);
140 re2 = compiler.compile("\r?\n", Perl5Compiler.READ_ONLY_MASK);
141 re3 = compiler.compile("BREAKHERE", Perl5Compiler.READ_ONLY_MASK);
143 catch (MalformedPatternException e) {
144 throw new RuntimeException(e.getMessage());
149 public PDFGenerator(ByteArrayOutputStream out) {
150 logger = new LoggerWrapper("PDFGenerator");
151 configuration = MirPropertiesConfiguration.instance();
152 localImageDir = configuration.getString("Producer.Image.Path");
155 indexFontSize = Integer.parseInt(configuration.getString("PDF.Index.FontSize"));
156 indexLineHeight = Integer.parseInt(configuration.getString("PDF.Index.LineHeight"));
157 indexFontFamily = getFontByName(configuration.getString("PDF.Index.FontFamily"));
159 footerText = configuration.getString("PDF.Footer.String");
160 footerFontSize = Integer.parseInt(configuration.getString("PDF.Footer.FontSize"));
161 footerFontFamily = getFontByName(configuration.getString("PDF.Footer.FontFamily"));
162 footerHeight = Integer.parseInt(configuration.getString("PDF.Footer.Height"));
164 metaFontSize = Integer.parseInt(configuration.getString("PDF.Meta.FontSize"));
165 metaFontFamily = getFontByName(configuration.getString("PDF.Meta.FontFamily"));
166 metaHeight = Integer.parseInt(configuration.getString("PDF.Meta.Height"));
168 descriptionFontSize = Integer.parseInt(configuration.getString("PDF.Description.FontSize"));
169 descriptionLineHeight = Integer.parseInt(configuration.getString("PDF.Description.LineHeight"));
170 descriptionFontFamily = getFontByName(configuration.getString("PDF.Description.FontFamily"));
172 contentFontSize = Integer.parseInt(configuration.getString("PDF.Content.FontSize"));
173 contentLineHeight = Integer.parseInt(configuration.getString("PDF.Content.LineHeight"));
174 contentFontFamily = getFontByName(configuration.getString("PDF.Content.FontFamily"));
176 sourceFontSize = Integer.parseInt(configuration.getString("PDF.Source.FontSize"));
177 sourceLineHeight = Integer.parseInt(configuration.getString("PDF.Source.LineHeight"));
178 sourceFontFamily = getFontByName(configuration.getString("PDF.Source.FontFamily"));
180 bigImageCaptionFontSize = Integer.parseInt(configuration.getString("PDF.BigImageCaption.FontSize"));
181 bigImageCaptionFontFamily = getFontByName(configuration.getString("PDF.BigImageCaption.FontFamily"));
184 catch (NumberFormatException e) {
185 throw new Failure(e.getMessage(), e);
188 // step 1: make a document
190 String pageSize = configuration.getString("PDF.Pagesize");
192 if (pageSize.equals("LETTER")) {
193 document = new Document(PageSize.LETTER);
197 document = new Document(PageSize.A4);
202 maxImageHeight = 250;
207 horizontalMargin = 20;
210 topEdge = pageHeight - verticalMargin;
211 bottomEdge = verticalMargin;
212 rightEdge = pageWidth - horizontalMargin;
213 leftEdge = horizontalMargin;
215 currentYPosition = topEdge;
218 String headerText = configuration.getString("PDF.Title.String");
221 writer = PdfWriter.getInstance(document, out);
222 cb = writer.getDirectContent();
225 addHeader(headerText);
227 catch (DocumentException de) {
228 logger.error(de.getMessage());
237 public void addHeader(String headerText) {
238 int titleFontSize = Integer.parseInt(configuration.getString("PDF.Title.FontSize"));
239 int titleLineHeight = Integer.parseInt(configuration.getString("PDF.Title.LineHeight"));
240 String titleFontFamily = configuration.getString("PDF.Title.FontFamily");
241 String headerImage = configuration.getString("PDF.Header.Image");
242 int headerImageHeight = Integer.parseInt(configuration.getString("PDF.Header.ImageHeight"));
245 if ((! headerImage.equals("")) && headerImageHeight != 0) {
246 PdfTemplate template = cb.createTemplate(rightEdge - horizontalMargin, headerImageHeight);
248 float toYPosition = currentYPosition - headerImageHeight;
249 Image theImage = Image.getInstance(headerImage);
250 theImage.setAbsolutePosition(0, 0);
251 // theImage.scaleAbsolute(img_width,img_height);
252 template.addImage(theImage);
255 cb.addTemplate(template, leftEdge, toYPosition);
256 currentYPosition = toYPosition;
258 if (! headerText.equals("")) {
259 ColumnText ct = new ColumnText(cb);
261 ct.addText(new Phrase(headerText, new Font(getFontByName(titleFontFamily), titleFontSize, Font.BOLD)));
262 float[] rightCol = {rightEdge, currentYPosition, rightEdge, currentYPosition - titleLineHeight};
263 float[] leftCol = {leftEdge, currentYPosition, leftEdge, currentYPosition - titleLineHeight};
264 ct.setColumns(leftCol, rightCol);
265 ct.setYLine(currentYPosition);
266 ct.setAlignment(Element.ALIGN_CENTER);
269 currentYPosition = currentYPosition - titleLineHeight;
272 catch (DocumentException de) {
273 logger.error(de.getMessage());
275 catch (MalformedURLException de) {
276 logger.error(de.getMessage());
278 catch (IOException de) {
279 logger.error(de.getMessage());
283 public void addIndexItem(EntityContent entityContent) {
286 ColumnText ict = new ColumnText(cb);
287 String theTitle = entityContent.getFieldValue("title");
288 String theCreator = entityContent.getFieldValue("creator");
289 Phrase titleP = new Phrase(" - " + theTitle, new Font(indexFontFamily, indexFontSize, Font.BOLD));
290 Phrase creatorP = new Phrase(" :: " + theCreator, new Font(indexFontFamily, indexFontSize));
291 float toYPosition = currentYPosition - indexLineHeight;
292 float[] leftIndexCols = {leftEdge, currentYPosition, leftEdge, toYPosition};
293 float[] rightIndexCols = {rightEdge, currentYPosition, rightEdge, toYPosition};
295 ict.addText(creatorP);
296 ict.setColumns(leftIndexCols, rightIndexCols);
297 ict.setYLine(currentYPosition);
298 ict.setAlignment(Element.ALIGN_LEFT);
300 currentYPosition = toYPosition;
302 catch (DocumentException de) {
303 logger.error(de.getMessage());
309 private int addTextLine(ColumnText ct, int lineHeight, int alignment, float left, float right) {
310 logger.debug("adding a line of text");
311 if (! enoughY(lineHeight)) {
314 float toYPosition = currentYPosition - lineHeight;
315 float[] leftContentCols = {left, currentYPosition, left, toYPosition};
316 float[] rightContentCols = {right, currentYPosition, right, toYPosition};
317 ct.setColumns(leftContentCols, rightContentCols);
318 ct.setYLine(currentYPosition);
319 ct.setAlignment(alignment);
321 int status = ct.go();
322 currentYPosition = toYPosition;
325 catch (DocumentException de) {
326 logger.error(de.getMessage());
331 public void addLine() {
333 cb.moveTo(rightEdge, currentYPosition - 5);
334 cb.lineTo(leftEdge, currentYPosition - 5);
336 currentYPosition = currentYPosition - 10;
340 public void addFooter() {
342 ColumnText fct = new ColumnText(cb);
344 cb.moveTo(rightEdge, bottomEdge + footerHeight - 5);
345 cb.lineTo(leftEdge, bottomEdge + footerHeight - 5);
347 float[] leftFooterCols = {leftEdge, bottomEdge + footerHeight - 1, leftEdge, bottomEdge};
348 float[] rightFooterCols = {rightEdge, bottomEdge + footerHeight - 1, rightEdge, bottomEdge};
350 Paragraph footerP = new Paragraph(footerText, new Font(footerFontFamily, footerFontSize));
351 fct.addText(footerP);
353 fct.setColumns(leftFooterCols, rightFooterCols);
354 fct.setYLine(bottomEdge + footerHeight - 1);
355 fct.setAlignment(Element.ALIGN_JUSTIFIED);
358 Paragraph numberP = new Paragraph((new Integer(currentPage)).toString(), new Font(footerFontFamily, footerFontSize, Font.BOLD));
359 fct.addText(numberP);
360 fct.setAlignment(Element.ALIGN_RIGHT);
364 catch (DocumentException de) {
365 logger.error(de.getMessage());
371 public void newPage() {
377 currentYPosition = topEdge;
379 catch (DocumentException de) {
380 logger.error(de.getMessage());
384 public void addArticleSeparator() {
390 cb.moveTo(rightEdge, currentYPosition - 5);
391 cb.lineTo(leftEdge, currentYPosition - 5);
393 currentYPosition = currentYPosition - 10;
396 public void addArticleMetaInfo(ColumnText ct, String theTitle, String theCreator, String theDate) {
397 //see if we have room for the author and title
399 if (! enoughY(metaHeight)) {
403 Paragraph titleP = new Paragraph(theTitle + "\n", new Font(metaFontFamily, metaFontSize, Font.BOLD));
404 Paragraph whowhenP = new Paragraph(theCreator + " " + theDate, new Font(metaFontFamily, metaFontSize));
406 ct.addText(whowhenP);
408 ct.setYLine(currentYPosition);
409 ct.setAlignment(Element.ALIGN_LEFT);
411 float toYPosition = currentYPosition - metaHeight;
412 float[] leftHeadCols = {leftEdge, currentYPosition, leftEdge, toYPosition};
413 float[] rightHeadCols = {rightEdge, currentYPosition, rightEdge, toYPosition};
415 ct.setColumns(leftHeadCols, rightHeadCols);
418 currentYPosition = toYPosition;
420 catch (DocumentException de) {
421 logger.error(de.getMessage());
426 public void addArticleDescription(ColumnText ct, String theDescription) {
427 // Now we add the description, one line at a time, the ct should be empty at this point
430 Paragraph descP = new Paragraph(theDescription, new Font(descriptionFontFamily, descriptionFontSize, Font.BOLD));
433 // every article has a description, so we can assume that:
434 int status = ColumnText.NO_MORE_COLUMN;
437 while ((status & ColumnText.NO_MORE_TEXT) == 0 && brake > 0) {
438 //there is still text left in the description.
439 status = addTextLine(ct, descriptionLineHeight, Element.ALIGN_JUSTIFIED, leftEdge, rightEdge);
443 logger.error("runaway description...try increasing the line height or decreasing the font size");
446 public void addArticleContent(ColumnText ct, String theContent, Iterator images) {
447 //let's go ahead and add in all the body text
448 Paragraph contentP = new Paragraph(theContent, new Font(contentFontFamily, contentFontSize));
449 ct.addText(contentP);
451 int contentLinesBeforeImages = 3;
452 //and assume we have at least one line of text in the content
453 int status = ColumnText.NO_MORE_COLUMN;
455 // let's add a little bit of text, like a couple of lines
457 while (((status & ColumnText.NO_MORE_TEXT) == 0) && x < contentLinesBeforeImages) {
458 status = addTextLine(ct, contentLineHeight, Element.ALIGN_JUSTIFIED, leftEdge, rightEdge);
462 boolean addImageOnLeft = true; //we will alternate within articles
463 while (images.hasNext()) {
465 EntityImages currentImage = (EntityImages) images.next();
466 float img_width = (new Float(currentImage.getFieldValue("img_width"))).floatValue();
467 float img_height = (new Float(currentImage.getFieldValue("img_height"))).floatValue();
468 if (img_height > maxImageHeight) {
469 img_width = (new Float((new Float(img_width * (maxImageHeight / img_height))).intValue())).floatValue();
470 img_height = maxImageHeight;
472 if (img_width > maxImageWidth) {
473 img_height = (new Float((new Float(img_height * (maxImageWidth / img_width))).intValue())).floatValue();
474 img_width = maxImageWidth;
477 String img_title = currentImage.getFieldValue("title");
478 String img_path = currentImage.getFieldValue("publish_path");
480 if ((status & ColumnText.NO_MORE_TEXT) == 0) {
481 // there is still text, so add an image which will have text wrapped around it, then add the text which
482 // will be on the left or the right of the image
484 float templateMinimumHeight = img_height + 20;
485 float templateWidth = img_width + 10;
486 float templateHeight = templateMinimumHeight + contentLineHeight - (templateMinimumHeight % contentLineHeight);
488 PdfTemplate template = cb.createTemplate(templateWidth, templateHeight);
490 //here we need a page check
491 if (! enoughY((new Float(templateHeight)).intValue())) {
492 //ok, well just fill text to the bottom then
493 float toYPosition = bottomEdge + footerHeight;
494 float[] leftBottomCols = {leftEdge, currentYPosition, leftEdge, toYPosition};
495 float[] rightBottomCols = {rightEdge, currentYPosition, rightEdge, toYPosition};
496 ct.setColumns(leftBottomCols, rightBottomCols);
497 ct.setYLine(currentYPosition);
498 ct.setAlignment(Element.ALIGN_JUSTIFIED);
502 catch (DocumentException de) {
503 logger.error(de.getMessage());
508 float toYPosition = currentYPosition - templateHeight;
511 Image theImage = Image.getInstance(localImageDir + img_path);
512 theImage.scaleAbsolute(img_width, img_height);
513 theImage.setAbsolutePosition(5, 13);
515 template.addImage(theImage);
516 template.beginText();
517 BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
518 template.setFontAndSize(bf, 8);
519 template.setTextMatrix(5, 3);
520 template.showText(img_title);
523 catch (BadElementException de) {
524 logger.error(de.getMessage());
526 catch (DocumentException de) {
527 logger.error(de.getMessage());
529 catch (MalformedURLException de) {
530 logger.error(de.getMessage());
532 catch (IOException de) {
533 logger.error(de.getMessage());
537 float leftImageTextEdge = leftEdge;
538 float rightImageTextEdge = rightEdge;
541 if (addImageOnLeft) {
542 cb.addTemplate(template, leftEdge, toYPosition);
543 leftImageTextEdge = leftEdge + templateWidth + 5;
544 addImageOnLeft = false;
546 cb.addTemplate(template, rightEdge - templateWidth, toYPosition);
547 rightImageTextEdge = rightEdge - templateWidth - 5;
548 addImageOnLeft = true;
551 logger.debug("adding template at " + leftEdge + "," + toYPosition);
553 //and fill some text while we are at it
555 float[] leftBottomCols = {leftImageTextEdge, currentYPosition, leftImageTextEdge, toYPosition};
556 float[] rightBottomCols = {rightImageTextEdge, currentYPosition, rightImageTextEdge, toYPosition};
557 ct.setColumns(leftBottomCols, rightBottomCols);
558 ct.setYLine(currentYPosition);
559 ct.setAlignment(Element.ALIGN_JUSTIFIED);
562 currentYPosition = toYPosition;
564 catch (DocumentException de) {
565 logger.error(de.getMessage());
570 //add an image on the left with a big caption to the right
571 currentYPosition = currentYPosition - 10;
572 float templateMinimumHeight = img_height;
573 float templateWidth = img_width;
574 float templateHeight = templateMinimumHeight + contentLineHeight - (templateMinimumHeight % contentLineHeight);
575 PdfTemplate template = cb.createTemplate(templateWidth, templateHeight);
576 if (! enoughY((new Float(templateHeight)).intValue())) {
579 float toYPosition = currentYPosition - templateHeight;
581 Image theImage = Image.getInstance(localImageDir + img_path);
582 theImage.setAbsolutePosition(0, 13);
583 theImage.scaleAbsolute(img_width, img_height);
584 template.addImage(theImage);
586 catch (BadElementException de) {
587 logger.error(de.getMessage());
589 catch (DocumentException de) {
590 logger.error(de.getMessage());
592 catch (MalformedURLException de) {
593 logger.error(de.getMessage());
595 catch (IOException de) {
596 logger.error(de.getMessage());
599 cb.addTemplate(template, leftEdge, toYPosition);
602 ColumnText cct = new ColumnText(cb);
603 float[] leftCaptionCols = {leftEdge + templateWidth + 5, currentYPosition - 5, leftEdge + templateWidth + 5, toYPosition};
604 float[] rightCaptionCols = {rightEdge, currentYPosition - 5, rightEdge, toYPosition};
606 Paragraph captionP = new Paragraph(img_title, new Font(bigImageCaptionFontFamily, bigImageCaptionFontSize, Font.BOLD));
607 cct.addText(captionP);
608 cct.setColumns(leftCaptionCols, rightCaptionCols);
609 cct.setYLine(currentYPosition - 5);
610 cct.setAlignment(Element.ALIGN_LEFT);
613 currentYPosition = toYPosition;
615 catch (DocumentException de) {
616 logger.error(de.getMessage());
621 //add the rest of the text which might be left
623 while ((status & ColumnText.NO_MORE_TEXT) == 0 && brake > 0) {
624 status = addTextLine(ct, contentLineHeight, Element.ALIGN_JUSTIFIED, leftEdge, rightEdge);
628 logger.error("runaway content....try decreasing font size or increasing line height");
631 private void addArticleSource(ColumnText ct, String theSource) {
632 Paragraph sourceP = new Paragraph(theSource, new Font(sourceFontFamily, sourceFontSize, Font.BOLD));
634 addTextLine(ct, sourceLineHeight, Element.ALIGN_RIGHT, leftEdge, rightEdge);
638 private boolean enoughY(int heightOfBlockToAdd) {
639 return (currentYPosition - heightOfBlockToAdd - footerHeight) >= bottomEdge;
643 public void add(EntityContent anArticle, Locale aLocale) throws GeneratorExc, MirLocalizerExc, Exception {
644 logger.debug("adding a content Entity");
654 * --image without text
658 List extraTables = new ArrayList();
659 extraTables.add("content_x_media cxm");
660 Iterator images = new EntityBrowser(
661 DatabaseImages.getInstance(), "i", extraTables,
662 "cxm.content_id=" + anArticle.getId() + "and cxm.media_id=i.id",
663 "i.id desc", 30, -1, 0);
665 String isHTML = anArticle.getFieldValue("is_html");
666 String theTitle = anArticle.getFieldValue("title");
667 String theCreator = anArticle.getFieldValue("creator");
668 String theDate = DateTimeRoutines.advancedDateFormat(
669 configuration.getString("RDF.Meta.DateFormat"),
670 StringUtil.convertMirInternalDateToDate(anArticle.getFieldValue("webdb_create")),
671 configuration.getString("Mir.DefaultTimezone"));
674 String theDescriptionRaw = anArticle.getFieldValue("description");
675 String theContentRaw = anArticle.getFieldValue("content_data");
677 MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();
678 Map variables = GeneratorHelper.makeBasicGenerationData(new Locale[] {
679 aLocale ,new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), "")},
680 "bundles.open","bundles.open");
682 EntityAdapter article =
683 MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("content", anArticle);
684 variables.put("article", article);
685 String source = ParameterExpander.expandExpression(
687 configuration.getString("PDF.Source")
689 String theContent = "";
690 String theDescription = "";
692 if (isHTML.equals("1")) {
694 Util.substitute(new Perl5Matcher(), nobackslashr, new Perl5Substitution(""), theContentRaw, Util.SUBSTITUTE_ALL);
696 Util.substitute(new Perl5Matcher(), nobackslashr, new Perl5Substitution(""), theDescriptionRaw, Util.SUBSTITUTE_ALL);
698 theContent = Util.substitute(new Perl5Matcher(), HxTag, new Perl5Substitution("\n\n"), theContent, Util.SUBSTITUTE_ALL);
699 theDescription = Util.substitute(new Perl5Matcher(), HxTag, new Perl5Substitution("\n\n"), theDescription, Util.SUBSTITUTE_ALL);
700 theContent = Util.substitute(new Perl5Matcher(), ListItemTag, new Perl5Substitution("\n * "), theContent, Util.SUBSTITUTE_ALL);
701 theDescription = Util.substitute(new Perl5Matcher(), ListItemTag, new Perl5Substitution("\n * "), theDescription, Util.SUBSTITUTE_ALL);
703 theContent = Util.substitute(new Perl5Matcher(), ListTag, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL);
704 theDescription = Util.substitute(new Perl5Matcher(), ListTag, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL);
706 theContent = Util.substitute(new Perl5Matcher(), DivTag, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL);
707 theDescription = Util.substitute(new Perl5Matcher(), DivTag, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL);
709 theContent = Util.substitute(new Perl5Matcher(), PTag, new Perl5Substitution("\n "), theContent, Util.SUBSTITUTE_ALL);
710 theDescription = Util.substitute(new Perl5Matcher(), PTag, new Perl5Substitution("\n "), theDescription, Util.SUBSTITUTE_ALL);
712 theContent = Util.substitute(new Perl5Matcher(), PTagClose, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL);
713 theDescription = Util.substitute(new Perl5Matcher(), PTagClose, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL);
715 theContent = Util.substitute(new Perl5Matcher(), BRTag, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL);
716 theDescription = Util.substitute(new Perl5Matcher(), BRTag, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL);
719 Perl5Matcher matcher = new Perl5Matcher();
720 PatternMatcherInput input = new PatternMatcherInput(theContent);
721 String theContentCopy = theContent;
722 while (matcher.contains(input, ATagAll)) {
723 String atagString = matcher.getMatch().group(0);
724 String atagStringHref = matcher.getMatch().group(1);
725 String atagStringText = matcher.getMatch().group(2);
726 int begin = matcher.getMatch().beginOffset(0);
728 theContentCopy.substring(0, begin) + atagStringText +
729 " [" + atagStringHref + "] " + theContentCopy.substring(begin + atagString.length());
731 theContent = theContentCopy;
734 input = new PatternMatcherInput(theDescription);
736 String theDescriptionCopy = theDescription;
737 while (matcher.contains(input, ATagAll)) {
738 String atagString = matcher.getMatch().group(0);
739 String atagStringHref = matcher.getMatch().group(1);
740 String atagStringText = matcher.getMatch().group(2);
741 int begin = matcher.getMatch().beginOffset(0);
742 theDescriptionCopy = theDescriptionCopy.substring(0, begin) + atagStringText + " [" + atagStringHref + "] " +
743 theDescriptionCopy.substring(begin + atagString.length());
745 theDescription = theDescriptionCopy;
748 theContent = Util.substitute(new Perl5Matcher(), noTags, new Perl5Substitution(" "), theContent, Util.SUBSTITUTE_ALL);
749 theDescription = Util.substitute(new Perl5Matcher(), noTags, new Perl5Substitution(" "), theDescription, Util.SUBSTITUTE_ALL);
751 theContent = HTMLRoutines.resolveHTMLEntites(theContent);
752 theDescription = HTMLRoutines.resolveHTMLEntites(theDescription);
754 String theDescription1 = Util.substitute(new Perl5Matcher(), re1, new Perl5Substitution("BREAKHERE"), theDescription, Util.SUBSTITUTE_ALL);
756 String theDescription2 = Util.substitute(new Perl5Matcher(), re2, new Perl5Substitution(" "), theDescription1, Util.SUBSTITUTE_ALL);
758 theDescription = Util.substitute(new Perl5Matcher(), re3, new Perl5Substitution("\n "), theDescription2, Util.SUBSTITUTE_ALL);
761 String theContent1 = Util.substitute(new Perl5Matcher(), re1,
762 new Perl5Substitution("BREAKHERE"), theContentRaw, Util.SUBSTITUTE_ALL);
763 String theDescription1 = Util.substitute(new Perl5Matcher(), re1,
764 new Perl5Substitution("BREAKHERE"), theDescriptionRaw, Util.SUBSTITUTE_ALL);
766 String theContent2 = Util.substitute(new Perl5Matcher(), re2,
767 new Perl5Substitution(" "), theContent1, Util.SUBSTITUTE_ALL);
768 String theDescription2 = Util.substitute(new Perl5Matcher(), re2,
769 new Perl5Substitution(" "), theDescription1, Util.SUBSTITUTE_ALL);
771 theContent = " " + Util.substitute(new Perl5Matcher(), re3,
772 new Perl5Substitution("\n "), theContent2, Util.SUBSTITUTE_ALL);
773 theDescription = Util.substitute(new Perl5Matcher(), re3,
774 new Perl5Substitution("\n "), theDescription2, Util.SUBSTITUTE_ALL);
777 addArticleSeparator();
779 ColumnText ct = new ColumnText(cb);
781 addArticleMetaInfo(ct, theTitle, theCreator, theDate);
782 addArticleDescription(ct, theDescription);
783 addArticleContent(ct, theContent, images);
784 addArticleSource(ct, source);
787 public int getFontByName(String fontName) {
789 if ("helvetica".equalsIgnoreCase(fontName)) {
790 theFont = Font.HELVETICA;
792 else if ("courier".equalsIgnoreCase(fontName)) {
793 theFont = Font.COURIER;
795 else if ("times".equalsIgnoreCase(fontName)) {
796 theFont = Font.TIMES_ROMAN;
799 logger.error("using helvetica because I can't get font for name: " + fontName);
800 theFont = Font.HELVETICA;