PDF Output¶
- Author
Yewondwossen Assefa
- Contact
yassefa at dmsolutions.ca
- Last Updated
2006-01-12
Table of Contents
Introduction¶
PDF output support was added to MapServer 3.7. Previous versions of MapServer had support for pdf output using a utility program (shp2pdf) to output a pdf file given a MapServer mapfile.
The difference in this new version is that the output to PDF can now be directly specified in the mapfile using the IMAGETYPE or the OUTPUTFORMAT parameters in the mapfile. Additionally, raster layers are now supported for pdf output.
Note
From version 6.0, PDF output is supported through Cairo. This is not reflected in the current documentation.
What is currently supported and not supported¶
Vector Layers
Layer Point: supported
Layer Line: supported
Layer Polygon: supported
Layer Circle : not supported
Note
Note: Dashed lines are supported with PDFlib version 6 or greater.
Note
Polygons filled with symbols are not supported.
Raster Layers
Raster layers are supported. Note that at this point all raster layers are transformed to jpeg format before being written to the PDF file.
WMS Layers
Not yet supported
Surround components
Legend, scalebar are not supported.
Fonts
Standard PostScript fonts are supported. For use of other fonts (such as truetype), see the pdflib documentation for use of UPR description files (some notes on it are here).
Implementing PDF Output¶
Note that the following instructions were developed for MapServer 3.7 and pdflib 4.0.3, but the general steps should be similar for recent versions of both.
Build the PDF Library¶
In order to have access to the PDF support in MapServer, you should download and build the PDF library from http://www.pdflib.com/products/pdflib/. Please follow the instructions on the PDFLib site to build on your specific platforms.
Here are some quick notes on how to build on windows:
download and extract the source code from https://www.pdflib.com/products/pdflib-family/pdflib/
open the project PDFlib.dsw in MS Visual C++
build the project pdflib_dll
after a successful build, you should have a pdflib.lib and pdblib.dll under the pdflib directory
copy the pdflib.dll under your system directory (ex : c:/winnt/system32)
the pdflib.lib will be used while building MapServer with the PDF support
Build MapServer with PDF support¶
Windows platform
Edit the makefile.vc and uncomment the following lines (make sure that the paths are adapted to your installation):
PDF_LIB=../pdflib-4.0.3/pdflib/pdflib.lib
PDF_INC=-I../pdflib-4.0.3/pdflib
PDF=-DUSE_PDF
See the Windows Compilation document for general MapServer compile instructions.
Unix platforms
Add with-pdf to your configure command line before compiling.
See the Unix Compilation document for general MapServer compile instructions.
Mapfile definition¶
The IMAGETYPE parameter in the Mapfile should be set to pdf in order to output to PDF:
NAME pdf-test
STATUS ON
...
IMAGETYPE pdf
..
WEB
...
END
LAYER
...
END
END
You can also specify the output using the OUTPUTFORMAT tag (this tag was introduced in mapserver 3.7) :
OUTPUTFORMAT
NAME pdf
MIMETYPE "application/x-pdf"
DRIVER pdf
FORMATOPTION "OUTPUT_TYPE=RASTER" ##not mandatory
END
If the OUTPUT_TYPE=RASTER all the layers will be rendered as rasters. Note that when WMS layers are included in the mapfile, this option should be set since there is a problem with transparency and wms layers. See the OUTPUTFORMAT object in the Mapfile reference for parameter explanations.
Testing¶
The easiest way to test your pdf output mapfile is with the MapServer shp2img utility. Windows users can find this utility in MS4W, as well as FWTools.
You simply pass a mapfile to the executable and a name for the output pdf, and a pdf file is generated:
shp2img -m gmap_pdf.map -o test.pdf
Possible Errors¶
PDFlib I/O error: Resource configuration file 'pdflib.upr' not found
This is related to fonts. If you remove the LABEL object from your mapfile you will see this error go away. The pdf error is described here. Basically, until this issue is ‘fixed’, if you want to use a font other than the included standard PostScript fonts in pdf output (such as truetype fonts), consult the PDFlib documentation.
PHP/MapScript and PDF Output¶
MapServer can render to PDF directly, another option is to render to a PNG and insert that into a PDF document. This is not the only way to create a PDF document of course. You will need to have support for PDFLib compiled into your PHP install.
This example shows the key parts of the process, you will need to furnish parts of the script yourself (depending on your app) and repeat the process for each map element that you want to include.
Refer to the PHP/MapScript Reference wherever necessary.
How does it work?¶
In brief, we will pass parameters required to render a map to a PHP script that will:
create a PDF document
render a PNG view at a suitably higher resolution
insert the PNG
buffer it and send it to the user
Create the PDF document¶
Here is an example similar to the one given on the PHP website to create a new PDF document:
$my_pdf = pdf_new();
...
Get this stage and section 4.5 working before you try inserting MapServer elements.
Render PNG views at a suitable resolution¶
Work back from the assumption that you will need no more than 300 dpi on your page for your map to look presentable. For an A4 map, I am using 150 dpi for an 8’ x 8’ main map, which is 1200 x 1200 pixels.
$map->set(width,1200);
$map->set(height,1200);
Of course, our map will not be very useful unless it is zoomed in to the extent our user requested, and the layers they selected are switched on. Maintain arrays in your application that record:
- The current extent (say $ext[])
- Layer status (say $layer[])
Open your map file and pass these back through to set the map file into the state the user is expecting, something like:
$map->setextent($ext[0], $ext[1], $ext[2], $ext[3]);
while($layer[]) {
$layer=$map->getLayer($n);
if($layer[$n]==1) {
$layer->set(status,1);
} else {
$layer->set(status,0);
}
}
Now you will need to save a rendered view to a PNG file.
$img = $map->draw();
$url = $img->saveWebImage(MS_PNG, 0, 0, 0);
Use the same method for all your map elements, such as drawReferenceMap?(), drawScaleBar?() and drawLegend().
Insert the PNG elements into your PDF document¶
This is really easy, use the pdf_open_image_file() function to import the map elements into your PDF document:
$element = pdf_open_image_file($my_pdf, "png", "$webroot/$url");
pdf_place_image($my_pdf, $element, $xpos, $ypos);
pdf_close_image($my_pdf, $element);
Repeat as needed for any map elements you created.
Buffer the PDF and send it to the user¶
Assuming we have been creating the document $my_pdf, when we are done, we merely buffer it and send it to the user using echo():
<?php
....
pdf_close($my_pdf);
$data = pdf_get_buffer($my_pdf);
header('Content-type: application/pdf');
header('Content-disposition: inline; filename=my_pdf.pdf');
header('Content-length: ' . strlen($data) );
echo $data;
?>
Gotcha: remember that you cannot send headers if you have at any stage outputed text to the browser.
Additional stuff to try¶
Rendering everything as PNG can look ugly, so I step through the key and extract labels so I can render them using PDF’s text functions.
This can be done for other map element, such as map titles, layer descriptions, or anything else that can be read from the mapfile.