Version 23 (modified by pvalsecc, 6 years ago)

--

General architecture

This module is split in two:

  1. Client side, a set of JS classes:
    • mapfish.PrintProtocol: Non-GUI dependant class for communicating with the server side.
    • mapfish.widgets.print.SimpleForm: Ext panel allowing to print a single page document.
    • mapfish.widgets.print.MultiPage: Ext panel allowing to print a multipage document.
  2. Server side, three implementations:
    • ShellMapPrinter: A command line implementation of the map printing service. Used mainly by the python implementation and for debug.
    • MapPrinterServlet: A java servlet implementing the protocol used by mapfish.PrintProtocol.
    • PrinterController: A Pylons servlet implementing the protocol used by mapfish.PrintProtocol. It uses ShellMapPrinter to enter the java world and do the work.

The server side uses a YAML configuration file that defines the page layouts and allowed values. For more details see the "Server side Configuration" chapter.

The client side, before displaying the forms, can request the server side about the available page layouts, the allowed scales and resolutions.

Server side Configuration

Here is the general structure:

dpis:
  - 254
  - 190
  {...}

scales:
  - 25000
  - 50000
  {...}

hosts:
  - {HOST_WHITELIST_DEFINITION}
  {...}

layouts:
  {LAYOUT_NAME}:
?   titlePage:
?     {PAGE_DEFINITION}
    mainPage:
      {PAGE_DEFINITION}
  {...}

Optional parts are shown with a question mark in the left margin. The question marks must not be put in the configuration file. Their default values is shown.

In general, PDF dimensions and positions are specified in points. 72 points == 1 inch == 25.4 mm.

The list of {HOST_WHITELIST_DEFINITION} defines the allowed URLs for getting maps. Its format will be defined in the next sub-section.

You can have as many layouts as you want. Their name must be unique and will be used on the client side. A layout can have a "titlePage" that will be added at the beginning of the generated document. It cannot contain any map. The "mainPage" section is mandatory and will be used once for each page requested. The details of a {PAGE_DEFINITION} section can be found in another sub-section of this document.

Host whitelist definition

There are 3 ways to whitelist a host.

Allowing every local services:

  - !localMatch
    dummy: true

The "dummy" parameter is ignored, but mandatory to avoid a limitation in the YAML format.

Allowing by DNS name:

  - !dnsMatch
    host: labs.metacarta.com

Allowing by IP address:

  - !ipMatch
    ip: www.camptocamp.org

The "ip" parameter can be a DNS name that will be resolved or directly an IP address.

All the methods accept the following optional parameters:

  • port: to limit to a certain TCP port
  • pathRegexp: a regexp that must match the path part of the URL (before the '?').

Page definition

The structure is like that:

      pageSize: A4
?     landscape: false
?     marginLeft: 40
?     marginRight: 40
?     marginTop: 20
?     marginBottom: 20
?     backgroundPdf: template.pdf
?     header:
        height: 50
        items:
          - {BLOCK_DEFINITION}
          {...}
      items:
        - {BLOCK_DEFINITION}
        {...}
?     footer:
        height: 50
        items:
          - {BLOCK_DEFINITION}
          {...}

If "backgroundPdf" is specified, the first page of the given PDF file will be added as background of every page.

The "header" and "footer" sections are optional. If the "items" that are in the main section are too big, more pages are generated. The header and footer will be drawn on those pages as well.

Block definition

The next sub-sections document the possible types of blocks.

In general, text values or URLs can contain values taken from the spec structure coming with the client's request. A syntax similar to shell is used: ${variableName}. If the current page is a titlePage, only the root values are taken. If it's a mainPage, the service will first look in the current page section then in the root values. Here is how to use this functionality:

            text: 'The value of mapTitle is: ${mapTitle}'

Some virtual variables can be used:

  • ${pageNum}: The current page number.
  • ${pageTot}: The total number of pages. Can be used only in text blocks.
  • ${now}: The current date and time as defined by the machine's locale.
  • ${now FORMAT}: The current date and time as defined by the FORMAT string. The syntax is documented here.
  • ${configDir}: The absolute path to the directory of the configuration file.

Text block

        - !text
?         font: Helvetica
?         fontSize: 12
?         spacingAfter: 0
?         align: left
?         vertAlign: middle
?         backgroundColor: #FFFFFF
          text: 'Blahblah'

Image block

        - !image
          maxWidth: 200
          maxHeight: 100
?         spacingAfter: 0
?         align: left
?         vertAlign: middle
          url: http://trac.mapfish.org/trac/mapfish/chrome/site/img/mapfish.png

Supported formats are PNG, GIF, Jpeg, Jpeg2000, BMP, WMF (vector) and TIFF.

The original aspect ratio will be respected. The url can contain "${}" variables.

Columns block

        - !columns
?         widths: [25,25,25,25]
?         backgroundColor: #FFFFFF
?         absoluteX: null
?         absoluteY: null
?         width: {PAGE_WIDTH}
?         spacingAfter: 0
          items:
            - {BLOCK_DEFINITION}
            {...}

By default, the width of the columns will be equal.

Each item will be in its own column.

If the absoluteX, absoluteY and width are given, the columns block will be floating on top of the page at the specified position.

Every block type is allowed except for map if the column has an absolute position.

Map block

Allowed only within a mainPage.

        - !map
?         spacingAfter: 0
?         align: left
?         vertAlign: middle
?         absoluteX: null
?         absoluteY: null
?         absoluteX: null
?         overviewMap: null
          width: 440
          height: 483

If the absoluteX, absoluteY and width are given, the map block will be floating on top of the page at the specified position.

If overviewMap is specified, the map will be an overview of the extent augmented by the given factor.

Scalebar block

Display a scalebar.

Allowed only within a mainPage.

        - !scalebar
          maxSize: 150
?         type: line
?         intervals: 3
?         subIntervals: false
?         units: m
?         barSize: 5
?         lineWidth: 1
?         barDirection: up
?         textDirection: up
?         labelDistance: 3
?         font: Helvetica
?         fontSize: 12
?         color: #000000
?         barBgColor: null
?         spacingAfter: 0
?         align: left
?         vertAlign: middle
?         backgroundColor: #FFFFFF

The scalebar, will adapt its width up to maxSize in order to have a multiple of 1, 2 or 5 values at each graduation. For example:

  • 0, 1, 2, ...
  • 0, 2, 4, ...
  • 0, 5, 10, ...
  • 0, 10, 20, ...

The barSize is the thickness of the bar or the height of the tick marks on the line. The lineWith is for the thickness of the lines (or bar border).

Units can be any of:

  • m (mm, cm, m or km)
  • ft (in, ft, yd, mi)
  • degrees (min, sec, °)

If the value is too big or too small, the module will switch to one of the unit in parenthesis (the same unit is used for every intervals).

The number of intervals can be set to anything >=2. Labels are drawn only at main intervals. If there is no space to display a label at a certain interval, this label won't be displayed. If subIntervals are enabled, their number will depend on the length of an interval.

The type can be:

  • line: A simple line with graduations
  • bar: A thick bar with a suite of color and barBgColor blocks.
  • bar_sub: Like bar, but with little lines for labels.

Error: Macro Image(scalebarTypes.png) failed
Attachment 'wiki:PrintModuleDoc: scalebarTypes.png' does not exist.

The bar and/or text orientation can be set to "up", "down", "left" or "right".

The align attribute is for placing the whole scalebar withing the surrounding column or page. The vertAlign attribute is used only when placed in a column.

Labels are always centered on the graduation, at a distance specified by labelDistance.

Attributes block

Allows to display a table of the displayed feature's attributes. Not implemented on the client side, since it's supposed to be integrated with the query module which is not yet done.

Allowed only within a mainPage.

        - !attributes
          source: data
          columnDefs:
            {COLUMN_NAME}:
              header: {BLOCK_DEFINITION}
              cell: {BLOCK_DEFINITION}
            {...}

The source value defines the name of the entry in the root of the client's spec. For example, it would look like that:

{
  ...
  pages: [
    {
      ...
      data: {
        {id:1, name: 'blah', icon: 'icon_pan'},
        ...
      }
    }
  ]
  ...
}

With this data you would have to define 3 columnDefs with the names id, name and icon. The cell definition blocks have access to all the values of the current row.

Here is a crazy example of columnDef that will show the name of the icon and it's bitmap side-by-side inside a single column:

          columnDefs:
            icon:
              header: !text
                text: Symbol
                backgroundColor: #A0A0A0
              cell: !columns
                items:
                  - !text
                    text: '${icon}'
                  - !image
                    align: center
                    maxWidth: 15
                    maxHeight: 15
                    url: 'http://www.mapfish.org/svn/mapfish/trunk/MapFish/client/mfbase/mapfish/img/${icon}.png'

Protocol

Four commands are available and are documented in the next sections.

Every command uses the HTTP status code to notify errors.

info.json

HTTP command:

GET {PRINT_URL}/info.json?url={PRINT_URL}%2Finfo.json&var=printConfig

Returns a JSON structure as such:

var printConfig = {
    "scales":[
        {"name":"25000"},
        {"name":"50000"},
        {"name":"100000"}
    ],
    "dpis":[
        {"name":"190"},
        {"name":"254"}
    ],
    "layouts":[
        {
            "name":"A4 portrait",
            "map":{
                "width":440,
                "height":483
            }
        }
    ],
    "printURL":"http:\/\/localhost:5000\/print\/print.pdf",
    "createURL":"http:\/\/localhost:5000\/print\/create.json"
}

This can be loaded through an HTML script tag like that:

<script type="text/javascript"
        src="http://localhost:5000/print/info.json?var=printConfig"></script>

Or through an AJAX request by omitting the "var" query parameter. All the print widget implementations have a "configUrl" parameter. If this parameter is set, the widget will do this request by AJAX automatically.

The "url" query parameter is here to help the print servlet to know what URL is used by the browser to access the servlet. This parameter is here because the servlet can be behind a proxy, hiding the real URL.

print.pdf

HTTP command:

GET {PRINT_URL}/print.pdf?spec={SPEC}

The "SPEC" parameter is a JSON structure like that:

{
    layout: 'A4 portrait',
    ...CUSTOM_PARAMS...
    srs: 'EPSG:4326',
    units: 'degrees',
    layers: [
        {
            type: 'WMS',
            layers: ['basic'],
            baseURL: 'http://labs.metacarta.com/wms/vmap0',
            format: 'image/jpeg'
        }
    ],
    pages: [
        {
            center: [6, 45.5],
            scale: 4000000,
            dpi: 190,
            ...CUSTOM_PARAMS...
        }
    ]
}

There are two locations where custom parameters can be added. Those will be ignored by the web service but, will be accessible from the layout templates.

For the format of the layers section, please look at the implementations pointed by mapfish.PrintProtocol.SUPPORTED_TYPES.

This command returns the PDF file directly.

create.json

HTTP command:

POST {PRINT_URL}/create.json?url={PRINT_URL}%2Fcreate.json

The spec defined in the "print.pdf" command must be included in the POST body.

Returns a JSON structure like that:

{
    getURL: 'http:\/\/localhost:5000\/print\/56723.pdf'
}

The URL returned can be used to retrieve the PDF file. See the next section.

{ID}.pdf

This command's URL is returned by the "create.json" command.

HTTP command:

GET {PRINT_URL}/{ID}.pdf

Returns the PDF. Can be called only once since the server side temporary file is deleted afterwards.

Client side

Please look at the examples in examples/print/ examples/print/.

Overrides

All the JS classes are accepting an overrides parameters. This parameter can be used to change the OL layers settings just for the print output. This can be usefull for several purpose:

  • Go around a TileCache server and access the WMS server directly (baseURL and layers).
  • Change the format of the requested map (format).
  • Change the style (styles).

Any value passed in the spec can be overridden like this.

It is a dictionary where the key are the layer's names and the values are dictionaries of parameters to change when printing.

For example:

var overrides = {
  'rivers': {
    format: 'image/svg+xml'
  },
  'far': {
    visibility: false
  }
}

In this case, the rivers layer will be printed vectorized (type 2 layer) and the far layer won't be printed.

Installation

Please read the README.

FAQ

I tried to print (pylons mode) and I get a "Java error". What's next?

Look in the apache error log, you'll find more information.

What are the limitations of the type 2 layers?

It depends mostly on the map server you use. For the moment, GeoServer has not been extensively tested. With MapServer:

  • The PDF output must be enabled when you compile and doesn't work in WMS mode, only in native MapServer mode. There are some limitations. on the styling. And you must use truetype fonts.
  • The SVG output is limited regarding the stylings you can use. For example only plain polygon fillings are supported by MapServer. If a complex styling is used, your features may appear plain black.

I tried to change the layout and half the Map is printed off the page on the right. Or I have an empty page added. Is it a bug?

It's mostly a feature ;-) . This kind of behavior can be seen in iText, when adding a block that is too big for the page size. Try to reduce the size of your map block.

I have a layer that has 1 color and the rest is transparent. In the PDF, it shows up with a black background, why?

It's a bug in iText. As a work around, enable anti-aliasing or stop using indexed colors for this layer.