001: //=============================================================================
002: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
003: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
004: //=== and United Nations Environment Programme (UNEP)
005: //===
006: //=== This program is free software; you can redistribute it and/or modify
007: //=== it under the terms of the GNU General Public License as published by
008: //=== the Free Software Foundation; either version 2 of the License, or (at
009: //=== your option) any later version.
010: //===
011: //=== This program is distributed in the hope that it will be useful, but
012: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
013: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: //=== General Public License for more details.
015: //===
016: //=== You should have received a copy of the GNU General Public License
017: //=== along with this program; if not, write to the Free Software
018: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
019: //===
020: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
021: //=== Rome - Italy. email: geonetwork@osgeo.org
022: //==============================================================================
023:
024: package org.wfp.vam.intermap.services.export;
025:
026: import com.lowagie.text.*;
027: import com.lowagie.text.pdf.*;
028:
029: import java.awt.Color;
030: import java.awt.image.BufferedImage;
031: import java.io.File;
032: import java.io.FileOutputStream;
033: import java.util.HashMap;
034: import java.util.Map;
035: import jeeves.interfaces.Service;
036: import jeeves.server.ServiceConfig;
037: import jeeves.server.context.ServiceContext;
038: import org.jdom.Element;
039: import org.wfp.vam.intermap.kernel.GlobalTempFiles;
040: import org.wfp.vam.intermap.kernel.map.MapMerger;
041: import org.wfp.vam.intermap.kernel.map.images.ImageMerger;
042: import org.wfp.vam.intermap.kernel.map.images.ImageUtils;
043: import org.wfp.vam.intermap.kernel.map.images.ScaleBar;
044: import org.wfp.vam.intermap.kernel.map.mapServices.BoundingBox;
045: import org.wfp.vam.intermap.services.map.MapUtil;
046: import org.wfp.vam.intermap.util.Util;
047:
048: public class ExportPDF implements Service {
049: private final static int MAP_WIDTH_PX = 1160;
050: private final static int MAP_HEIGHT_PX = 870;
051:
052: private String _northarrowfile;
053:
054: public void init(String appPath, ServiceConfig config)
055: throws Exception {
056: _northarrowfile = config.getMandatoryValue("northArrowImage");
057: }
058:
059: public Element exec(Element params, ServiceContext context)
060: throws Exception {
061: MapMerger mm = MapUtil.getMapMerger(context);
062:
063: Rectangle pagesize = parsePagesize(params
064: .getChildText("pagesize"));
065: boolean isLandscape = isLandscape(params
066: .getChildText("orientation"));
067: if (isLandscape)
068: pagesize = pagesize.rotate();
069:
070: BoundingBox bb = Util.parseBoundingBox(params); // search bb in params
071: if (bb != null)
072: mm.setBoundingBox(bb);
073:
074: String title = params.getChildText("title");
075: String copyright = params.getChildText("copyright");
076:
077: boolean drawScale = "on"
078: .equals(params.getChildText("scalebar"));
079: boolean drawArrow = "on".equals(params.getChildText("arrow"));
080: boolean showLayerList = "on".equals(params
081: .getChildText("layerlist"));
082: boolean showDetails = "on".equals(params
083: .getChildText("details"));
084:
085: Document document = new Document(pagesize);
086:
087: File pdfFile = GlobalTempFiles.getInstance().getFile(".pdf");
088: PdfWriter pw = PdfWriter.getInstance(document,
089: new FileOutputStream(pdfFile));
090:
091: document.addTitle(title != null ? title
092: : "GeoNetwork opensource Map");
093: document.addSubject("");
094: document.addCreator("GeoNetwork opensource map viewer");
095: document.addCreationDate();
096: document.addAuthor("ETj");
097: document.addProducer();
098: document.addKeywords(getKeywords(mm));
099: if (copyright != null)
100: document.addHeader("Copyright note", copyright);
101:
102: if (copyright != null)
103: pw.setPageEvent(new PE(copyright));
104:
105: document.open();
106:
107: // TITLE
108: if (title != null) {
109: Font font = new Font(Font.HELVETICA, 20, Font.NORMAL);
110: Paragraph para = new Paragraph(title, font);
111: para.setAlignment(Paragraph.ALIGN_CENTER);
112: document.add(para);
113: }
114:
115: // IMAGE
116: String map = mm.merge(MAP_WIDTH_PX, MAP_HEIGHT_PX);
117: String mapImageFullPath = mm.getImageLocalPath()
118: .getAbsolutePath()
119: + File.separatorChar + map;
120:
121: if (drawArrow) {
122: BufferedImage arrow = ImageUtils.load(_northarrowfile);
123: BufferedImage mapimage = ImageUtils.load(mapImageFullPath);
124: BufferedImage rect = ImageUtils.createRect(mapimage
125: .getWidth()
126: + arrow.getWidth() + 10, mapimage.getHeight(),
127: Color.WHITE);
128: BufferedImage merged;
129: merged = ImageMerger.merge(rect, mapimage, 0, 0);
130: merged = ImageMerger.merge(merged, arrow, -1, 5);
131:
132: // BufferedImage merged = ImageMerger.merge(mapImageFullPath, _northarrowfile, -5, 5);
133: mapImageFullPath = GlobalTempFiles.getInstance().getFile()
134: .getPath(); // we need a new file: MapMerger could reuse its own file
135: ImageMerger.saveImage(merged, mapImageFullPath,
136: ImageMerger.PNG);
137: }
138:
139: if (drawScale) {
140: BufferedImage sb = ScaleBar.getScaleBar(
141: mm.getBoundingBox(), MAP_WIDTH_PX, 150);
142: BufferedImage rect = ImageUtils.createRect(
143: sb.getWidth() + 10, sb.getHeight() + 10,
144: Color.WHITE);
145:
146: BufferedImage merged;
147: merged = ImageMerger.merge(mapImageFullPath, rect, 1, -1,
148: .5f);
149: merged = ImageMerger.merge(merged, sb, 5, -5);
150:
151: mapImageFullPath = GlobalTempFiles.getInstance().getFile()
152: .getPath(); // we need a new file: drawArrow may be not requested
153: ImageMerger.saveImage(merged, mapImageFullPath,
154: ImageMerger.PNG);
155: }
156:
157: Image mapImage = Image.getInstance(mapImageFullPath);
158: mapImage.scaleToFit(500, 400);
159: mapImage.setAlignment(Image.MIDDLE);
160: document.add(mapImage);
161:
162: if (showLayerList) {
163: document.add(new Paragraph("Layers list:")); // FIXME: i18n me!
164: List llist = new List(true, 20);
165:
166: for (int i = 0; i < mm.size(); i++) {
167: ListItem litem = getLayerPara(mm, i, showDetails);
168: llist.add(litem);
169: }
170:
171: document.add(llist);
172: }
173:
174: if (params.getChildText("boundingbox") != null) // the user wants the bbox
175: {
176: // Be careful: the requested bbox may have been reaspected to keep the image dimensions ratio
177: // Let's say we'll print the reaspected bbox
178:
179: PdfPTable t = getBBTable(mm.getBoundingBox());
180: t.setSpacingBefore(30);
181: document.add(t);
182: }
183:
184: document.close();
185:
186: return new Element("response").addContent(new Element("pdf")
187: .addContent(new Element("url").setText(MapUtil
188: .getTempUrl()
189: + "/" + pdfFile.getName())));
190: }
191:
192: private ListItem getLayerPara(MapMerger mm, int layerRank,
193: boolean showDetails) {
194: ListItem litem = new ListItem();
195:
196: // Add layer name
197: String servicename = mm.getServiceRanked(layerRank).getTitle();
198: Chunk name = new Chunk(servicename);
199:
200: if (!mm.isVisibleRanked(layerRank)) {
201: Font font = new Font();
202: font.setStyle(Font.STRIKETHRU);
203: name.setFont(font);
204: }
205: litem.add(name);
206:
207: if (showDetails) // the user wants details
208: {
209: // Add transparency info
210: Font font = new Font();
211: font.setSize(Font.DEFAULTSIZE * 0.8f);
212: font.setStyle(Font.ITALIC);
213: int trasp = mm.getLayerTransparencyRanked(layerRank);
214: if (trasp != 100) {
215: Chunk transp = new Chunk(" ("
216: + mm.getLayerTransparencyRanked(layerRank)
217: + "%)", font);
218: litem.add(transp);
219: }
220: }
221: return litem;
222: }
223:
224: private String getKeywords(MapMerger mm) {
225: StringBuffer sb = new StringBuffer(
226: "GeoNetwork opensource, OSGeo");
227:
228: for (int layerRank = 0; layerRank < mm.size(); layerRank++) {
229: if (mm.isVisibleRanked(layerRank)) {
230: String servicename = mm.getServiceRanked(layerRank)
231: .getName();
232: sb.append(", ").append(servicename);
233: }
234: }
235:
236: return sb.toString();
237: }
238:
239: private static PdfPTable getBBTable(BoundingBox bb) {
240: PdfPTable t = new PdfPTable(3);
241:
242: PdfPCell empty = new PdfPCell(new Paragraph(""));
243: empty.setBorder(0);
244:
245: PdfPCell n = new PdfPCell(new Paragraph("N: " + bb.getNorth()));
246: n.setVerticalAlignment(Cell.ALIGN_MIDDLE);
247: n.setHorizontalAlignment(Cell.ALIGN_CENTER);
248: PdfPCell e = new PdfPCell(new Paragraph("E: " + bb.getEast()));
249: e.setVerticalAlignment(Cell.ALIGN_MIDDLE);
250: e.setHorizontalAlignment(Cell.ALIGN_LEFT);
251: PdfPCell w = new PdfPCell(new Paragraph("W: " + bb.getWest()));
252: w.setVerticalAlignment(Cell.ALIGN_MIDDLE);
253: w.setHorizontalAlignment(Cell.ALIGN_RIGHT);
254: PdfPCell s = new PdfPCell(new Paragraph("S: " + bb.getSouth()));
255: s.setVerticalAlignment(Cell.ALIGN_MIDDLE);
256: s.setHorizontalAlignment(Cell.ALIGN_CENTER);
257:
258: t.addCell(new PdfPCell(empty));
259: t.addCell(n);
260: t.addCell(new PdfPCell(empty));
261:
262: t.addCell(w);
263: t.addCell(new PdfPCell(empty));
264: t.addCell(e);
265:
266: t.addCell(new PdfPCell(empty));
267: t.addCell(s);
268: t.addCell(new PdfPCell(empty));
269:
270: return t;
271: }
272:
273: private boolean isLandscape(String o) {
274: if (o.equalsIgnoreCase("landscape"))
275: return true;
276: else if (o.equalsIgnoreCase("portrait"))
277: return false;
278: else
279: return false; // Set the default value to your liking
280: }
281:
282: private static final Map<String, Rectangle> PAGESIZE = new HashMap<String, Rectangle>();
283: static {
284: PAGESIZE.put("a4", PageSize.A4);
285: PAGESIZE.put("a3", PageSize.A3);
286: PAGESIZE.put("letter", PageSize.LETTER);
287: PAGESIZE.put("legal", PageSize.LEGAL);
288: // This list may be extended with other pagesize values
289: }
290:
291: private Rectangle parsePagesize(String ps) {
292: Rectangle ret = PAGESIZE.get(ps);
293: if (ret == null)
294: ret = PageSize.A4; // set the default pagesize as you like
295:
296: return ret;
297: }
298:
299: static class PE extends PdfPageEventHelper {
300: protected PdfTemplate total;
301: protected BaseFont _watermarkFont;
302: protected PdfGState gstate;
303: protected Phrase footer;
304:
305: protected String _watermarkText;
306:
307: public PE(String watermark) {
308: this ._watermarkText = watermark;
309:
310: footer = new Phrase(watermark);
311: Font font = new Font();
312: font.setSize(Font.DEFAULTSIZE * 0.9f);
313: font.setStyle(Font.ITALIC);
314: footer.setFont(font);
315: }
316:
317: public void onOpenDocument(PdfWriter writer, Document document) {
318: total = writer.getDirectContent().createTemplate(100, 100);
319: total.setBoundingBox(new Rectangle(-20, -20, 100, 100));
320:
321: try {
322: _watermarkFont = BaseFont.createFont(
323: BaseFont.HELVETICA, BaseFont.WINANSI,
324: BaseFont.NOT_EMBEDDED);
325: } catch (Exception e) {
326: throw new ExceptionConverter(e);
327: }
328:
329: gstate = new PdfGState();
330: gstate.setFillOpacity(0.3f);
331: gstate.setStrokeOpacity(0.3f);
332: }
333:
334: public void onEndPage(PdfWriter writer, Document document) {
335: boolean showWaterMark = false;
336: if (showWaterMark) {
337: // Draw watermark
338: PdfContentByte contentunder = writer.getDirectContent();
339: contentunder.saveState();
340: contentunder.setGState(gstate);
341: contentunder.setColorFill(Color.blue);
342: contentunder.beginText();
343: contentunder.setFontAndSize(_watermarkFont, 48);
344: contentunder.showTextAligned(
345: com.lowagie.text.Element.ALIGN_CENTER,
346: _watermarkText, document.getPageSize()
347: .getWidth() / 2, document.getPageSize()
348: .getHeight() / 2, 45);
349: contentunder.endText();
350: contentunder.restoreState();
351: }
352:
353: // Draw footer
354: PdfContentByte cb = writer.getDirectContent();
355: ColumnText.showTextAligned(cb,
356: com.lowagie.text.Element.ALIGN_CENTER, footer,
357: (document.right() - document.left()) / 2
358: + document.leftMargin(),
359: document.bottom() - 10, 0);
360: }
361: }
362:
363: }
|