source: subversion/applications/rendering/osmarender6/osmarender.xsl @ 5516

Last change on this file since 5516 was 5516, checked in by brent, 12 years ago

Fix invalid utf-8

File size: 125.3 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3==============================================================================
4
5Osmarender 6.0 Alpha 5 orig area generation + one node way filtered out
6
7==============================================================================
8
9Copyright (C) 2006-2007  Etienne Cherdlu, Jochen Topf
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24
25==============================================================================
26-->
27<xsl:stylesheet
28  xmlns="http://www.w3.org/2000/svg"
29  xmlns:svg="http://www.w3.org/2000/svg"
30  xmlns:xlink="http://www.w3.org/1999/xlink"
31  xmlns:xi="http://www.w3.org/2001/XInclude"
32  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
33  xmlns:cc="http://web.resource.org/cc/"
34  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
35  xmlns:dc="http://purl.org/dc/elements/1.1/"
36  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
37  version="1.0">
38
39  <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="UTF-8"/>
40
41  <xsl:param name="osmfile" select="/rules/@data"/>
42  <xsl:param name="title" select="/rules/@title"/>
43
44  <xsl:param name="scale" select="/rules/@scale"/>
45  <xsl:param name="symbolScale" select="/rules/@symbolScale"/>
46  <xsl:param name='textAttenuation' select='/rules/@textAttenuation'/>
47  <xsl:param name="withOSMLayers" select="/rules/@withOSMLayers"/>
48  <xsl:param name="svgBaseProfile" select="/rules/@svgBaseProfile"/>
49  <xsl:param name="symbolsDir" select="/rules/@symbolsDir"/>
50
51  <xsl:param name="showGrid" select="/rules/@showGrid"/>
52  <xsl:param name="showBorder" select="/rules/@showBorder"/>
53  <xsl:param name="showScale" select="/rules/@showScale"/>
54  <xsl:param name="showLicense" select="/rules/@showLicense"/>
55
56  <xsl:key name="nodeById" match="/osm/node" use="@id"/>
57  <xsl:key name="wayById" match="/osm/way" use="@id"/>
58  <xsl:key name="wayByNode" match="/osm/way" use="nd/@ref"/>
59  <xsl:key name="relationByWay" match="/osm/relation" use="member/@ref"/>
60
61  <xsl:variable name="data" select="document($osmfile)"/>
62
63  <!-- Use a web-service (if available) to get the current date -->
64  <xsl:variable name="now" select="document('http://xobjex.com/service/date.xsl')" />
65  <xsl:variable name="date">
66    <xsl:choose>
67      <xsl:when test="$now">
68        <xsl:value-of select="substring($now/date/utc/@stamp,1,10)" />
69        <!-- Assumes 4 digit year -->
70      </xsl:when>
71      <xsl:otherwise>2007-01-01</xsl:otherwise>
72    </xsl:choose>
73  </xsl:variable>
74  <xsl:variable name="year">
75    <xsl:choose>
76      <xsl:when test="$now">
77        <xsl:value-of select="$now/date/utc/year" />
78      </xsl:when>
79      <xsl:otherwise>2007</xsl:otherwise>
80    </xsl:choose>
81  </xsl:variable>
82
83  <!-- extra height for marginalia at top -->
84  <xsl:variable name="marginaliaTopHeight">
85    <xsl:choose>
86      <xsl:when test="$title != ''">40</xsl:when>
87      <xsl:when test="($title = '') and ($showBorder = 'yes')">1.5</xsl:when>
88      <xsl:otherwise>0</xsl:otherwise>
89    </xsl:choose>
90  </xsl:variable>
91
92  <!-- extra height for marginalia at bottom -->
93  <xsl:variable name="marginaliaBottomHeight">
94    <xsl:choose>
95      <xsl:when test="($showScale = 'yes') or ($showLicense = 'yes')">45</xsl:when>
96      <xsl:when test="($showScale != 'yes') and ($showLicense != 'yes') and ($showBorder = 'yes')">1.5</xsl:when>
97      <xsl:otherwise>0</xsl:otherwise>
98    </xsl:choose>
99  </xsl:variable>
100
101  <!-- extra width for border -->
102  <xsl:variable name="extraWidth">
103    <xsl:choose>
104      <xsl:when test="$showBorder = 'yes'">3</xsl:when>
105      <xsl:otherwise>0</xsl:otherwise>
106    </xsl:choose>
107  </xsl:variable>
108
109  <!-- extra height for border -->
110  <xsl:variable name="extraHeight">
111    <xsl:choose>
112      <xsl:when test="($title = '') and ($showBorder = 'yes')">3</xsl:when>
113      <xsl:otherwise>0</xsl:otherwise>
114    </xsl:choose>
115  </xsl:variable>
116
117  <!-- Calculate the size of the bounding box based on the file content -->
118  <xsl:variable name="bllat">
119    <xsl:for-each select="$data/osm/node/@lat">
120      <xsl:sort data-type="number" order="ascending"/>
121      <xsl:if test="position()=1">
122        <xsl:value-of select="."/>
123      </xsl:if>
124    </xsl:for-each>
125  </xsl:variable>
126  <xsl:variable name="bllon">
127    <xsl:for-each select="$data/osm/node/@lon">
128      <xsl:sort data-type="number" order="ascending"/>
129      <xsl:if test="position()=1">
130        <xsl:value-of select="."/>
131      </xsl:if>
132    </xsl:for-each>
133  </xsl:variable>
134  <xsl:variable name="trlat">
135    <xsl:for-each select="$data/osm/node/@lat">
136      <xsl:sort data-type="number" order="descending"/>
137      <xsl:if test="position()=1">
138        <xsl:value-of select="."/>
139      </xsl:if>
140    </xsl:for-each>
141  </xsl:variable>
142  <xsl:variable name="trlon">
143    <xsl:for-each select="$data/osm/node/@lon">
144      <xsl:sort data-type="number" order="descending"/>
145      <xsl:if test="position()=1">
146        <xsl:value-of select="."/>
147      </xsl:if>
148    </xsl:for-each>
149  </xsl:variable>
150  <xsl:variable name="bottomLeftLatitude">
151    <xsl:choose>
152      <xsl:when test="/rules/bounds">
153        <xsl:value-of select="/rules/bounds/@minlat"/>
154      </xsl:when>
155      <xsl:when test="$data/osm/bounds">
156        <xsl:value-of select="$data/osm/bounds/@request_minlat"/>
157      </xsl:when>
158      <xsl:otherwise>
159        <xsl:value-of select="$bllat"/>
160      </xsl:otherwise>
161    </xsl:choose>
162  </xsl:variable>
163  <xsl:variable name="bottomLeftLongitude">
164    <xsl:choose>
165      <xsl:when test="/rules/bounds">
166        <xsl:value-of select="/rules/bounds/@minlon"/>
167      </xsl:when>
168      <xsl:when test="$data/osm/bounds">
169        <xsl:value-of select="$data/osm/bounds/@request_minlon"/>
170      </xsl:when>
171      <xsl:otherwise>
172        <xsl:value-of select="$bllon"/>
173      </xsl:otherwise>
174    </xsl:choose>
175  </xsl:variable>
176  <xsl:variable name="topRightLatitude">
177    <xsl:choose>
178      <xsl:when test="/rules/bounds">
179        <xsl:value-of select="/rules/bounds/@maxlat"/>
180      </xsl:when>
181      <xsl:when test="$data/osm/bounds">
182        <xsl:value-of select="$data/osm/bounds/@request_maxlat"/>
183      </xsl:when>
184      <xsl:otherwise>
185        <xsl:value-of select="$trlat"/>
186      </xsl:otherwise>
187    </xsl:choose>
188  </xsl:variable>
189  <xsl:variable name="topRightLongitude">
190    <xsl:choose>
191      <xsl:when test="/rules/bounds">
192        <xsl:value-of select="/rules/bounds/@maxlon"/>
193      </xsl:when>
194      <xsl:when test="$data/osm/bounds">
195        <xsl:value-of select="$data/osm/bounds/@request_maxlon"/>
196      </xsl:when>
197      <xsl:otherwise>
198        <xsl:value-of select="$trlon"/>
199      </xsl:otherwise>
200    </xsl:choose>
201  </xsl:variable>
202
203  <!-- Derive the latitude of the middle of the map -->
204  <xsl:variable name="middleLatitude" select="($topRightLatitude + $bottomLeftLatitude) div 2.0"/>
205  <!--woohoo lets do trigonometry in xslt -->
206  <!--convert latitude to radians -->
207  <xsl:variable name="latr" select="$middleLatitude * 3.1415926 div 180.0"/>
208  <!--taylor series: two terms is 1% error at lat<68 and 10% error lat<83. we probably need polar projection by then -->
209  <xsl:variable name="coslat" select="1 - ($latr * $latr) div 2 + ($latr * $latr * $latr * $latr) div 24"/>
210  <xsl:variable name="projection" select="1 div $coslat"/>
211
212  <xsl:variable name="dataWidth" select="(number($topRightLongitude)-number($bottomLeftLongitude))*10000*$scale"/>
213  <xsl:variable name="dataHeight" select="(number($topRightLatitude)-number($bottomLeftLatitude))*10000*$scale*$projection"/>
214  <xsl:variable name="km" select="(0.0089928*$scale*10000*$projection)"/>
215
216  <xsl:variable name="documentWidth">
217    <xsl:choose>
218      <xsl:when test="$dataWidth &gt; (number(/rules/@minimumMapWidth) * $km)">
219        <xsl:value-of select="$dataWidth"/>
220      </xsl:when>
221      <xsl:otherwise>
222        <xsl:value-of select="number(/rules/@minimumMapWidth) * $km"/>
223      </xsl:otherwise>
224    </xsl:choose>
225  </xsl:variable>
226
227  <xsl:variable name="documentHeight">
228    <xsl:choose>
229      <xsl:when test="$dataHeight &gt; (number(/rules/@minimumMapHeight) * $km)">
230        <xsl:value-of select="$dataHeight"/>
231      </xsl:when>
232      <xsl:otherwise>
233        <xsl:value-of select="number(/rules/@minimumMapHeight) * $km"/>
234      </xsl:otherwise>
235    </xsl:choose>
236  </xsl:variable>
237
238  <xsl:variable name="width" select="($documentWidth div 2) + ($dataWidth div 2)"/>
239  <xsl:variable name="height" select="($documentHeight div 2) + ($dataHeight div 2)"/>
240
241
242
243  <!-- Main template -->
244  <xsl:template match="/rules">
245
246    <!-- Include an external css stylesheet if one was specified in the rules file -->
247    <xsl:if test="@xml-stylesheet">
248      <xsl:processing-instruction name="xml-stylesheet">
249        href="<xsl:value-of select="@xml-stylesheet"/>" type="text/css"
250      </xsl:processing-instruction>
251    </xsl:if>
252
253    <xsl:variable name="svgWidth" select="$documentWidth + $extraWidth"/>
254    <xsl:variable name="svgHeight" select="$documentHeight + $marginaliaTopHeight + $marginaliaBottomHeight"/>
255
256    <svg id="main"
257  version="1.1"
258  baseProfile="{$svgBaseProfile}"
259  width="{$svgWidth}px"
260  height="{$svgHeight}px"
261  viewBox="{-$extraWidth div 2} {-$extraHeight div 2} {$svgWidth} {$svgHeight}">
262      <xsl:if test="/rules/@interactive='yes'">
263        <xsl:attribute name="onscroll">fnOnScroll(evt)</xsl:attribute>
264        <xsl:attribute name="onzoom">fnOnZoom(evt)</xsl:attribute>
265        <xsl:attribute name="onload">fnOnLoad(evt)</xsl:attribute>
266        <xsl:attribute name="onmousedown">fnOnMouseDown(evt)</xsl:attribute>
267        <xsl:attribute name="onmousemove">fnOnMouseMove(evt)</xsl:attribute>
268        <xsl:attribute name="onmouseup">fnOnMouseUp(evt)</xsl:attribute>
269      </xsl:if>
270
271      <xsl:call-template name="metadata"/>
272
273      <!-- Include javaScript functions for all the dynamic stuff -->
274      <xsl:if test="/rules/@interactive='yes'">
275        <xsl:call-template name="javaScript"/>
276      </xsl:if>
277
278
279      <defs id="defs-rulefile">
280        <!-- Get any <defs> and styles from the rules file -->
281        <xsl:copy-of select="defs/*"/>
282      </defs>
283
284
285      <xsl:if test="$symbolsDir != ''">
286        <!-- Get all symbols mentioned in the rules file from the symbolsDir -->
287        <defs id="defs-symbols">
288          <xsl:for-each select="/rules//symbol/@ref">
289            <xsl:copy-of select="document(concat($symbolsDir,'/', ., '.svg'))/svg:svg/svg:defs/svg:symbol"/>
290          </xsl:for-each>
291        </defs>
292      </xsl:if>
293
294      <!-- Pre-generate named path definitions for all ways -->
295      <xsl:variable name="allWays" select="$data/osm/way"/>
296      <defs id="defs-ways">
297        <xsl:for-each select="$allWays">
298          <xsl:call-template name="generateWayPaths"/>
299        </xsl:for-each>
300      </defs>
301
302      <!-- Clipping rectangle for map -->
303      <clipPath id="map-clipping">
304        <rect id="map-clipping-rect" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px"/>
305      </clipPath>
306
307      <g id="map" clip-path="url(#map-clipping)" inkscape:groupmode="layer" inkscape:label="Map" transform="translate(0,{$marginaliaTopHeight})">
308        <!-- Draw a nice background layer -->
309        <rect id="background" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px" class="map-background"/>
310
311        <!-- Process all the rules drawing all map features -->
312        <xsl:call-template name="processRules"/>
313      </g>
314
315      <!-- Draw map decoration -->
316      <g id="map-decoration" inkscape:groupmode="layer" inkscape:label="Map decoration" transform="translate(0,{$marginaliaTopHeight})">
317        <!-- Draw a grid if required -->
318        <xsl:if test="$showGrid='yes'">
319          <xsl:call-template name="drawGrid"/>
320        </xsl:if>
321
322        <!-- Draw a border if required -->
323        <xsl:if test="$showBorder='yes'">
324          <xsl:call-template name="drawBorder"/>
325        </xsl:if>
326      </g>
327
328      <!-- Draw map marginalia -->
329      <xsl:if test="($title != '') or ($showScale = 'yes') or ($showLicense = 'yes')">
330        <g id="marginalia" inkscape:groupmode="layer" inkscape:label="Marginalia">
331          <!-- Draw the title -->
332          <xsl:if test="$title!=''">
333            <xsl:call-template name="drawTitle">
334              <xsl:with-param name="title" select="$title"/>
335            </xsl:call-template>
336          </xsl:if>
337
338          <xsl:if test="($showScale = 'yes') or ($showLicense = 'yes')">
339            <g id="marginalia-bottom" inkscape:groupmode="layer" inkscape:label="Marginalia (Bottom)" transform="translate(0,{$marginaliaTopHeight})">
340              <!-- Draw background for marginalia at bottom -->
341              <rect id="marginalia-background" x="0px" y="{$documentHeight + 5}px" height="40px" width="{$documentWidth}px" class="map-marginalia-background"/>
342
343              <!-- Draw the scale in the bottom left corner -->
344              <xsl:if test="$showScale='yes'">
345                <xsl:call-template name="drawScale"/>
346              </xsl:if>
347
348              <!-- Draw Creative commons license -->
349              <xsl:if test="$showLicense='yes'">
350                <xsl:call-template name="in-image-license">
351                  <xsl:with-param name="dx" select="$documentWidth"/>
352                  <xsl:with-param name="dy" select="$documentHeight"/>
353                </xsl:call-template>
354              </xsl:if>
355            </g>
356          </xsl:if>
357        </g>
358      </xsl:if>
359
360      <!-- Draw labels and controls that are in a static position -->
361      <g id="staticElements" transform="scale(1) translate(0,0)">
362        <!-- Draw the +/- zoom controls -->
363        <xsl:if test="/rules/@interactive='yes'">
364          <xsl:call-template name="zoomControl"/>
365        </xsl:if>
366      </g>
367    </svg>
368
369  </xsl:template>
370
371  <!-- Path Fragment Drawing -->
372  <xsl:template name="drawPath">
373    <xsl:param name='instruction' />
374    <xsl:param name='pathId'/>
375    <xsl:param name='extraClasses'/>
376
377    <xsl:variable name="maskId" select="concat('mask_',$pathId)"/>
378
379    <xsl:call-template name='generateMask'>
380      <xsl:with-param name='instruction' select='$instruction'/>
381      <xsl:with-param name='pathId' select='$pathId'/>
382      <xsl:with-param name='maskId' select='$maskId'/>
383    </xsl:call-template>
384
385    <use xlink:href="#{$pathId}">
386      <!-- Copy all attributes from instruction -->
387      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes" />
388      <!-- Add in any extra classes -->
389      <xsl:attribute name="class">
390        <xsl:value-of select='$instruction/@class'/>
391        <xsl:text> </xsl:text>
392        <xsl:value-of select="$extraClasses"/>
393      </xsl:attribute>
394      <!-- If there is a mask class then include the mask attribute -->
395      <xsl:if test='$instruction/@mask-class'>
396        <xsl:attribute name="mask">
397          url(#<xsl:value-of select="$maskId"/>)
398        </xsl:attribute>
399      </xsl:if>
400      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
401    </use>
402  </xsl:template>
403
404
405  <xsl:template name='generateMask'>
406    <xsl:param name='instruction' />
407    <xsl:param name='pathId'/>
408    <xsl:param name='maskId'/>
409
410    <!-- If the instruction has a mask class -->
411    <xsl:if test='$instruction/@mask-class'>
412      <mask id="{$maskId}" maskUnits="userSpaceOnUse">
413        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-mask-black" />
414        <!-- Required for Inkscape bug -->
415        <use xlink:href="#{$pathId}" class="{$instruction/@class} osmarender-mask-white" />
416        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-mask-black" />
417      </mask>
418    </xsl:if>
419  </xsl:template>
420
421
422
423  <!-- Draw a line for the current <way> element using the formatting of the current <line> instruction -->
424  <xsl:template name="drawWay">
425    <xsl:param name="instruction"/>
426    <xsl:param name="way"/>
427    <!-- The current way element if applicable -->
428    <xsl:param name="layer"/>
429
430    <xsl:choose>
431      <xsl:when test="$instruction/@smart-linecap='no'">
432        <xsl:call-template name='drawPath'>
433          <xsl:with-param name='pathId' select="concat('way_normal_',$way/@id)"/>
434          <xsl:with-param name='instruction' select='$instruction'/>
435        </xsl:call-template>
436      </xsl:when>
437      <xsl:otherwise>
438        <xsl:call-template name="drawWayWithSmartLinecaps">
439          <xsl:with-param name="instruction" select="$instruction"/>
440          <xsl:with-param name="way" select="$way"/>
441          <xsl:with-param name="layer" select="$layer"/>
442        </xsl:call-template>
443      </xsl:otherwise>
444    </xsl:choose>
445  </xsl:template>
446
447
448  <xsl:template name="drawWayWithSmartLinecaps">
449    <xsl:param name="instruction"/>
450    <xsl:param name="way"/>
451    <!-- The current way element if applicable -->
452    <xsl:param name="layer"/>
453
454    <!-- The first half of the first segment and the last half of the last segment are treated differently from the main
455                        part of the way path.  The main part is always rendered with a butt line-cap.  Each end fragement is rendered with
456                        either a round line-cap, if it connects to some other path, or with its default line-cap if it is not connected
457                        to anything.  That way, cul-de-sacs etc are terminated with round, square or butt as specified in the style for the
458                        way. -->
459
460    <!-- First draw the middle section of the way with round linejoins and butt linecaps -->
461    <xsl:if test="count($way/nd) &gt; 1">
462      <xsl:call-template name='drawPath'>
463        <xsl:with-param name='pathId' select="concat('way_mid_',$way/@id)"/>
464        <xsl:with-param name='instruction' select='$instruction'/>
465        <xsl:with-param name='extraClasses'>osmarender-stroke-linecap-butt osmarender-no-marker-start osmarender-no-marker-end</xsl:with-param>
466      </xsl:call-template>
467    </xsl:if>
468
469
470    <!-- For the first half segment in the way, count the number of segments that link to the from-node of this segment.
471                        Also count links where the layer tag is less than the layer of this way, if there are links on a lower layer then
472                        we can safely draw a butt line-cap because the lower layer will already have a round line-cap. -->
473    <!-- Process the first segment in the way -->
474    <xsl:variable name="firstNode" select="key('nodeById',$way/nd[1]/@ref)"/>
475
476    <!-- Count the number of segments connecting to the from node. If there is only one (the current segment) then draw a default line.  -->
477    <xsl:variable name="firstNodeConnectionCount" select="count(key('wayByNode',$firstNode/@id))" />
478   
479    <!-- Count the number of connectors at a layer lower than the current layer -->
480    <xsl:variable name="firstNodeLowerLayerConnectionCount" select="
481                        count(key('wayByNode',$firstNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
482                        count(key('wayByNode',$firstNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
483                        " />
484    <xsl:choose>
485      <xsl:when test="$firstNodeConnectionCount=1">
486        <xsl:call-template name='drawPath'>
487          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
488          <xsl:with-param name='instruction' select='$instruction'/>
489          <xsl:with-param name="extraClasses">osmarender-no-marker-end</xsl:with-param>
490        </xsl:call-template>
491      </xsl:when>
492      <xsl:when test="$firstNodeLowerLayerConnectionCount>0">
493        <xsl:call-template name='drawPath'>
494          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
495          <xsl:with-param name='instruction' select='$instruction'/>
496          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-butt osmarender-no-marker-end</xsl:with-param>
497        </xsl:call-template>
498      </xsl:when>
499      <xsl:otherwise>
500        <xsl:call-template name='drawPath'>
501          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
502          <xsl:with-param name='instruction' select='$instruction'/>
503          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-round osmarender-no-marker-end</xsl:with-param>
504        </xsl:call-template>
505      </xsl:otherwise>
506
507    </xsl:choose>
508
509
510    <!-- Process the last segment in the way -->
511    <xsl:variable name="lastNode" select="key('nodeById',$way/nd[last()]/@ref)"/>
512
513    <!-- Count the number of segments connecting to the last node. If there is only one (the current segment) then draw
514                     a default line.  -->
515    <xsl:variable name="lastNodeConnectionCount" select="count(key('wayByNode',$lastNode/@id))" />
516    <!-- Count the number of connectors at a layer lower than the current layer -->
517    <xsl:variable name="lastNodeLowerLayerConnectionCount" select="
518                        count(key('wayByNode',$lastNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
519                        count(key('wayByNode',$lastNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
520                        " />
521
522
523    <xsl:choose>
524      <xsl:when test="$lastNodeConnectionCount=1">
525        <xsl:call-template name='drawPath'>
526          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
527          <xsl:with-param name='instruction' select='$instruction'/>
528          <xsl:with-param name="extraClasses">osmarender-no-marker-start</xsl:with-param>
529        </xsl:call-template>
530      </xsl:when>
531      <xsl:when test="$lastNodeLowerLayerConnectionCount>0">
532        <xsl:call-template name='drawPath'>
533          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
534          <xsl:with-param name='instruction' select='$instruction'/>
535          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-butt osmarender-no-marker-start</xsl:with-param>
536        </xsl:call-template>
537      </xsl:when>
538      <xsl:otherwise>
539        <xsl:call-template name='drawPath'>
540          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
541          <xsl:with-param name='instruction' select='$instruction'/>
542          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-round osmarender-no-marker-start</xsl:with-param>
543        </xsl:call-template>
544      </xsl:otherwise>
545
546    </xsl:choose>
547
548  </xsl:template>
549
550
551  <!-- Draw a circle for the current <node> element using the formatting of the current <circle> instruction -->
552  <xsl:template name="drawCircle">
553    <xsl:param name="instruction"/>
554
555    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
556    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
557
558    <circle cx="{$x}" cy="{$y}">
559      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
560      <!-- Copy all the svg attributes from the <circle> instruction -->
561    </circle>
562
563  </xsl:template>
564
565
566  <!-- Draw a symbol for the current <node> element using the formatting of the current <symbol> instruction -->
567  <xsl:template name="drawSymbol">
568    <xsl:param name="instruction"/>
569
570    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
571    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
572
573    <g transform="translate({$x},{$y}) scale({$symbolScale})">
574      <use>
575        <xsl:if test="$instruction/@ref">
576          <xsl:attribute name="xlink:href">
577            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
578          </xsl:attribute>
579        </xsl:if>
580        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
581        <!-- Copy all the attributes from the <symbol> instruction -->
582      </use>
583    </g>
584  </xsl:template>
585
586
587  <!-- Render the appropriate attribute of the current <node> element using the formatting of the current <text> instruction -->
588  <xsl:template name="renderText">
589    <xsl:param name="instruction"/>
590
591    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
592    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
593
594    <text>
595      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
596      <xsl:attribute name="x">
597        <xsl:value-of select="$x"/>
598      </xsl:attribute>
599      <xsl:attribute name="y">
600        <xsl:value-of select="$y"/>
601      </xsl:attribute>
602      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
603      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
604    </text>
605  </xsl:template>
606
607
608  <!-- Render the appropriate attribute of the current <segment> element using the formatting of the current <textPath> instruction -->
609  <xsl:template name="renderTextPath">
610    <xsl:param name="instruction"/>
611    <xsl:param name="pathId"/>
612    <xsl:param name="pathDirection"/>
613    <xsl:param name='text'/>
614
615    <xsl:variable name='pathLengthSquared'>
616      <xsl:call-template name='getPathLength'>
617        <xsl:with-param name='pathLengthMultiplier'>
618          <!-- This factor is used to adjust the path-length for comparison with text along a path to determine whether it will fit. -->
619          <xsl:choose>
620            <xsl:when test='$instruction/@textAttenuation'>
621              <xsl:value-of select='$instruction/@textAttenuation'/>
622            </xsl:when>
623            <xsl:when test='string($textAttenuation)'>
624              <xsl:value-of select='$textAttenuation'/>
625            </xsl:when>
626            <xsl:otherwise>99999999</xsl:otherwise>
627          </xsl:choose>
628        </xsl:with-param>
629        <xsl:with-param name='nodes' select='nd'/>
630      </xsl:call-template>
631    </xsl:variable>
632
633    <xsl:variable name='textLength' select='string-length($text)' />
634    <xsl:variable name='textLengthSquared100' select='($textLength)*($textLength)' />
635    <xsl:variable name='textLengthSquared90' select='($textLength *.9)*($textLength*.9)' />
636    <xsl:variable name='textLengthSquared80' select='($textLength *.8)*($textLength*.8)' />
637    <xsl:variable name='textLengthSquared70' select='($textLength *.7)*($textLength*.7)' />
638
639    <xsl:choose>
640      <xsl:when test='($pathLengthSquared) > $textLengthSquared100'>
641        <text>
642          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
643          <textPath xlink:href="#{$pathId}">
644            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
645            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
646            <xsl:value-of select="$text"/>
647          </textPath>
648        </text>
649      </xsl:when>
650      <xsl:when test='($pathLengthSquared) > ($textLengthSquared90)'>
651        <text>
652          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
653          <textPath xlink:href="#{$pathId}">
654            <xsl:attribute name='font-size'>90%</xsl:attribute>
655            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
656            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
657            <xsl:value-of select="$text"/>
658          </textPath>
659        </text>
660      </xsl:when>
661      <xsl:when test='($pathLengthSquared) > ($textLengthSquared80)'>
662        <text>
663          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
664          <textPath xlink:href="#{$pathId}">
665            <xsl:attribute name='font-size'>80%</xsl:attribute>
666            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
667            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
668            <xsl:value-of select="$text"/>
669          </textPath>
670        </text>
671      </xsl:when>
672      <xsl:when test='($pathLengthSquared) > ($textLengthSquared70)'>
673        <text>
674          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
675          <textPath xlink:href="#{$pathId}">
676            <xsl:attribute name='font-size'>70%</xsl:attribute>
677            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
678            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
679            <xsl:value-of select="$text"/>
680          </textPath>
681        </text>
682      </xsl:when>
683      <xsl:otherwise />
684      <!-- Otherwise don't render the text -->
685    </xsl:choose>
686  </xsl:template>
687
688
689  <xsl:template name='getPathLength'>
690    <xsl:param name='sumLon' select='number("0")' />
691    <!-- initialise sum to zero -->
692    <xsl:param name='sumLat' select='number("0")' />
693    <!-- initialise sum to zero -->
694    <xsl:param name='nodes'/>
695    <xsl:param name='pathLengthMultiplier'/>
696    <xsl:choose>
697      <xsl:when test='$nodes[1] and $nodes[2]'>
698        <xsl:variable name='fromNode' select='key("nodeById",$nodes[1]/@ref)'/>
699        <xsl:variable name='toNode' select='key("nodeById",$nodes[2]/@ref)'/>
700        <xsl:variable name='lengthLon' select='($fromNode/@lon)-($toNode/@lon)'/>
701        <xsl:variable name='absLengthLon'>
702          <xsl:choose>
703            <xsl:when test='$lengthLon &lt; 0'>
704              <xsl:value-of select='$lengthLon * -1'/>
705            </xsl:when>
706            <xsl:otherwise>
707              <xsl:value-of select='$lengthLon'/>
708            </xsl:otherwise>
709          </xsl:choose>
710        </xsl:variable>
711        <xsl:variable name='lengthLat' select='($fromNode/@lat)-($toNode/@lat)'/>
712        <xsl:variable name='absLengthLat'>
713          <xsl:choose>
714            <xsl:when test='$lengthLat &lt; 0'>
715              <xsl:value-of select='$lengthLat * -1'/>
716            </xsl:when>
717            <xsl:otherwise>
718              <xsl:value-of select='$lengthLat'/>
719            </xsl:otherwise>
720          </xsl:choose>
721        </xsl:variable>
722        <xsl:call-template name='getPathLength'>
723          <xsl:with-param name='sumLon' select='$sumLon+$absLengthLon'/>
724          <xsl:with-param name='sumLat' select='$sumLat+$absLengthLat'/>
725          <xsl:with-param name='nodes' select='$nodes[position()!=1]'/>
726          <xsl:with-param name='pathLengthMultiplier' select='$pathLengthMultiplier'/>
727        </xsl:call-template>
728      </xsl:when>
729      <xsl:otherwise>
730        <!-- Add the square of the total horizontal length to the square of the total vertical length to get the square of
731                                     the total way length.  We don't have a sqrt() function so leave it squared.
732                                     Multiply by 1,000 so that we are usually dealing with a values greater than 1.  Squares of values between 0 and 1
733                                     are smaller and so not very useful.
734                                     Multiply the latitude component by $projection to adjust for Mercator projection issues.
735                                     -->
736        <xsl:value-of select='(
737                                        (($sumLon*1000*$pathLengthMultiplier)*($sumLon*1000*$pathLengthMultiplier))+
738                                        (($sumLat*1000*$pathLengthMultiplier*$projection)*($sumLat*1000*$pathLengthMultiplier*$projection))
739                                        )'/>
740      </xsl:otherwise>
741    </xsl:choose>
742  </xsl:template>
743
744
745  <!-- Suppress the following attributes, allow everything else -->
746  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength|@k" mode="renderTextPath-text" />
747
748  <xsl:template match="@*" mode="renderTextPath-text">
749    <xsl:copy/>
750  </xsl:template>
751
752
753  <!-- Allow the following attributes, suppress everything else -->
754  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength" mode="renderTextPath-textPath">
755    <xsl:copy/>
756  </xsl:template>
757
758  <xsl:template match="@*" mode="renderTextPath-textPath" />
759
760
761  <!-- If there are any tags like <tag k="svg:font-size" v="5"/> then add these as attributes of the svg output -->
762  <xsl:template name="getSvgAttributesFromOsmTags">
763    <xsl:for-each select="tag[contains(@k,'svg:')]">
764      <xsl:attribute name="{substring-after(@k,'svg:')}">
765        <xsl:value-of select="@v"/>
766      </xsl:attribute>
767    </xsl:for-each>
768  </xsl:template>
769
770
771  <xsl:template name="renderArea">
772    <xsl:param name="instruction"/>
773    <xsl:param name="pathId"/>
774
775    <use xlink:href="#{$pathId}">
776      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
777    </use>
778  </xsl:template>
779
780
781  <!-- Templates to process line, circle, text, etc. instructions -->
782  <!-- Each template is passed a variable containing the set of elements that need to
783         be processed.  The set of elements is already determined by the rules, so
784         these templates don't need to know anything about the rules context they are in. -->
785
786  <!-- Process a <line> instruction -->
787  <xsl:template match="line">
788    <xsl:param name="elements"/>
789    <xsl:param name="layer"/>
790
791    <!-- This is the instruction that is currently being processed -->
792    <xsl:variable name="instruction" select="."/>
793
794    <g>
795      <xsl:apply-templates select="@*" mode="copyAttributes" />
796      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->
797
798      <!-- For each way -->
799      <xsl:apply-templates select="$elements" mode="line">
800        <xsl:with-param name="instruction" select="$instruction"/>
801        <xsl:with-param name="layer" select="$layer"/>
802      </xsl:apply-templates>
803
804    </g>
805  </xsl:template>
806
807
808  <!-- Suppress output of any unhandled elements -->
809  <xsl:template match="*" mode="line"/>
810
811
812  <!-- Draw lines for a way  -->
813  <xsl:template match="way" mode="line">
814    <xsl:param name="instruction"/>
815    <xsl:param name="layer"/>
816
817    <!-- The current <way> element -->
818    <xsl:variable name="way" select="."/>
819
820    <!-- DODI: !!!WORKAROUND!!! skip one node ways-->
821    <xsl:if test="count($way/nd) &gt; 1">
822      <xsl:call-template name="drawWay">
823        <xsl:with-param name="instruction" select="$instruction"/>
824        <xsl:with-param name="way" select="$way"/>
825        <xsl:with-param name="layer" select="$layer"/>
826      </xsl:call-template>
827    </xsl:if >
828  </xsl:template>
829
830
831  <!-- Process an <area> instruction -->
832  <xsl:template match="area">
833    <xsl:param name="elements"/>
834
835    <!-- This is the instruction that is currently being processed -->
836    <xsl:variable name="instruction" select="."/>
837
838    <g>
839      <xsl:apply-templates select="@*" mode="copyAttributes"/>
840      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->
841
842      <!-- For each way -->
843      <xsl:apply-templates select="$elements" mode="area">
844        <xsl:with-param name="instruction" select="$instruction"/>
845      </xsl:apply-templates>
846    </g>
847  </xsl:template>
848
849
850  <!-- Discard anything that is not matched by a more specific template -->
851  <xsl:template match="*" mode="area"/>
852
853
854  <!-- Draw area for a <way> -->
855  <xsl:template match="way" mode="area">
856    <xsl:param name="instruction"/>
857
858    <!-- DODI:  removed because duplicate definition generated if area referenced 2 or more times -->
859    <!-- DODI:  reenabled because of "duplicate point detection in lines2curves.pl " -->
860    <!-- <xsl:call-template name="generateAreaPath"/> -->
861
862    <xsl:variable name="pathArea">
863      <xsl:call-template name="generateAreaPath"/>
864    </xsl:variable>
865    <path id="area_{@id}" d="{$pathArea}"/>
866
867    <xsl:call-template name="renderArea">
868      <xsl:with-param name="instruction" select="$instruction"/>
869      <xsl:with-param name="pathId" select="concat('area_',@id)"/>
870    </xsl:call-template>
871
872  </xsl:template>
873
874
875  <!-- Process <circle> instruction -->
876  <xsl:template match="circle">
877    <xsl:param name="elements"/>
878
879    <!-- This is the instruction that is currently being processed -->
880    <xsl:variable name="instruction" select="."/>
881
882    <xsl:for-each select="$elements[name()='node']">
883      <xsl:call-template name="drawCircle">
884        <xsl:with-param name="instruction" select="$instruction"/>
885      </xsl:call-template>
886    </xsl:for-each>
887  </xsl:template>
888
889
890  <!-- Process a <symbol> instruction -->
891  <xsl:template match="symbol">
892    <xsl:param name="elements"/>
893
894    <!-- This is the instruction that is currently being processed -->
895    <xsl:variable name="instruction" select="."/>
896
897    <xsl:for-each select="$elements[name()='node']">
898      <xsl:call-template name="drawSymbol">
899        <xsl:with-param name="instruction" select="$instruction"/>
900      </xsl:call-template>
901    </xsl:for-each>
902
903  </xsl:template>
904
905
906  <!-- Process an <areaText> instruction -->
907  <xsl:template match="areaText">
908    <xsl:param name="elements"/>
909
910    <!-- This is the instruction that is currently being processed -->
911    <xsl:variable name="instruction" select="."/>
912
913    <!-- Select all <way> elements that have a key that matches the k attribute of the text instruction -->
914    <xsl:apply-templates select="$elements[name()='way'][tag[@k=$instruction/@k]]" mode="areaTextPath">
915      <xsl:with-param name="instruction" select="$instruction"/>
916    </xsl:apply-templates>
917  </xsl:template>
918
919
920  <xsl:template match="*" mode="areaTextPath"/>
921
922
923  <xsl:template match="way" mode="areaTextPath">
924    <xsl:param name="instruction"/>
925
926    <!-- The current <way> element -->
927    <xsl:variable name="way" select="."/>
928
929    <xsl:call-template name="renderAreaText">
930      <xsl:with-param name="instruction" select="$instruction"/>
931      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
932    </xsl:call-template>
933
934  </xsl:template>
935
936
937  <xsl:template name="renderAreaText">
938    <xsl:param name="instruction"/>
939
940    <xsl:variable name='left'>
941      <xsl:call-template name='areaExtentLeft'>
942        <xsl:with-param name='nd' select='./nd[1]'/>
943        <!-- First node -->
944        <xsl:with-param name='left' select='key("nodeById",./nd[1]/@ref)/@lon'/>
945        <!-- Longitude of first node -->
946      </xsl:call-template>
947    </xsl:variable>
948
949    <xsl:variable name='right'>
950      <xsl:call-template name='areaExtentRight'>
951        <xsl:with-param name='nd' select='./nd[1]'/>
952        <!-- First node -->
953        <xsl:with-param name='right' select='key("nodeById",./nd[1]/@ref)/@lon'/>
954        <!-- Longitude of first node -->
955      </xsl:call-template>
956    </xsl:variable>
957
958    <xsl:variable name='top'>
959      <xsl:call-template name='areaExtentTop'>
960        <xsl:with-param name='nd' select='./nd[1]'/>
961        <!-- First node -->
962        <xsl:with-param name='top' select='key("nodeById",./nd[1]/@ref)/@lat'/>
963        <!-- Latitude of first node -->
964      </xsl:call-template>
965    </xsl:variable>
966
967    <xsl:variable name='bottom'>
968      <xsl:call-template name='areaExtentBottom'>
969        <xsl:with-param name='nd' select='./nd[1]'/>
970        <!-- First node -->
971        <xsl:with-param name='bottom' select='key("nodeById",./nd[1]/@ref)/@lat'/>
972        <!-- Latitude of first node -->
973      </xsl:call-template>
974    </xsl:variable>
975
976    <xsl:variable name='midLon'>
977      <xsl:value-of select='$left+(($right - $left) div 2)'/>
978    </xsl:variable>
979    <xsl:variable name='midLat'>
980      <xsl:value-of select='$bottom+(($top - $bottom) div 2)'/>
981    </xsl:variable>
982
983    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($midLon))*10000*$scale)"/>
984    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($midLat))*10000*$scale*$projection)"/>
985
986    <text>
987      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
988      <xsl:attribute name="x">
989        <xsl:value-of select="$x"/>
990      </xsl:attribute>
991      <xsl:attribute name="y">
992        <xsl:value-of select="$y"/>
993      </xsl:attribute>
994      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
995      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
996    </text>
997  </xsl:template>
998
999
1000  <xsl:template name='areaExtentLeft'>
1001    <xsl:param name='nd'/>
1002    <xsl:param name='left'/>
1003
1004    <xsl:variable name='leftmostLon' select='key("nodeById",$nd/@ref)/@lon'/>
1005    <xsl:variable name='newLeft'>
1006      <xsl:choose>
1007        <xsl:when test='$left>$leftmostLon'>
1008          <xsl:value-of select='$leftmostLon'/>
1009        </xsl:when>
1010        <xsl:otherwise>
1011          <xsl:value-of select='$left'/>
1012        </xsl:otherwise>
1013      </xsl:choose>
1014    </xsl:variable>
1015
1016    <xsl:choose>
1017      <xsl:when test="$nd/following-sibling::nd[1]">
1018        <xsl:call-template name='areaExtentLeft'>
1019          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1020          <!-- next node -->
1021          <xsl:with-param name='left' select='$newLeft'/>
1022        </xsl:call-template>
1023      </xsl:when>
1024      <xsl:otherwise>
1025        <xsl:value-of select='$newLeft'/>
1026      </xsl:otherwise>
1027    </xsl:choose>
1028  </xsl:template>
1029
1030
1031  <xsl:template name='areaExtentRight'>
1032    <xsl:param name='nd'/>
1033    <xsl:param name='right'/>
1034
1035    <xsl:variable name='rightmostLon' select='key("nodeById",$nd/@ref)/@lon'/>
1036    <xsl:variable name='newRight'>
1037      <xsl:choose>
1038        <xsl:when test='$rightmostLon>$right'>
1039          <xsl:value-of select='$rightmostLon'/>
1040        </xsl:when>
1041        <xsl:otherwise>
1042          <xsl:value-of select='$right'/>
1043        </xsl:otherwise>
1044      </xsl:choose>
1045    </xsl:variable>
1046
1047    <xsl:choose>
1048      <xsl:when test="$nd/following-sibling::nd[1]">
1049        <xsl:call-template name='areaExtentRight'>
1050          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1051          <!-- next node -->
1052          <xsl:with-param name='right' select='$newRight'/>
1053        </xsl:call-template>
1054      </xsl:when>
1055      <xsl:otherwise>
1056        <xsl:value-of select='$newRight'/>
1057      </xsl:otherwise>
1058    </xsl:choose>
1059  </xsl:template>
1060
1061
1062  <xsl:template name='areaExtentTop'>
1063    <xsl:param name='nd'/>
1064    <xsl:param name='top'/>
1065
1066    <xsl:variable name='topmostLat' select='key("nodeById",$nd/@ref)/@lat'/>
1067    <xsl:variable name='newTop'>
1068      <xsl:choose>
1069        <xsl:when test='$top>$topmostLat'>
1070          <xsl:value-of select='$top'/>
1071        </xsl:when>
1072        <xsl:otherwise>
1073          <xsl:value-of select='$topmostLat'/>
1074        </xsl:otherwise>
1075      </xsl:choose>
1076    </xsl:variable>
1077
1078    <xsl:choose>
1079      <xsl:when test="$nd/following-sibling::nd[1]">
1080        <xsl:call-template name='areaExtentTop'>
1081          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1082          <!-- next node -->
1083          <xsl:with-param name='top' select='$newTop'/>
1084        </xsl:call-template>
1085      </xsl:when>
1086      <xsl:otherwise>
1087        <xsl:value-of select='$newTop'/>
1088      </xsl:otherwise>
1089    </xsl:choose>
1090  </xsl:template>
1091
1092
1093  <xsl:template name='areaExtentBottom'>
1094    <xsl:param name='nd'/>
1095    <xsl:param name='bottom'/>
1096
1097    <xsl:variable name='bottommostLat' select='key("nodeById",$nd/@ref)/@lat'/>
1098    <xsl:variable name='newBottom'>
1099      <xsl:choose>
1100        <xsl:when test='$bottommostLat>$bottom'>
1101          <xsl:value-of select='$bottom'/>
1102        </xsl:when>
1103        <xsl:otherwise>
1104          <xsl:value-of select='$bottommostLat'/>
1105        </xsl:otherwise>
1106      </xsl:choose>
1107    </xsl:variable>
1108
1109    <xsl:choose>
1110      <xsl:when test="$nd/following-sibling::nd[1]">
1111        <xsl:call-template name='areaExtentBottom'>
1112          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1113          <!-- next node -->
1114          <xsl:with-param name='bottom' select='$newBottom'/>
1115        </xsl:call-template>
1116      </xsl:when>
1117      <xsl:otherwise>
1118        <xsl:value-of select='$newBottom'/>
1119      </xsl:otherwise>
1120    </xsl:choose>
1121  </xsl:template>
1122
1123  <!-- Process a <text> instruction -->
1124  <xsl:template match="text">
1125    <xsl:param name="elements"/>
1126
1127    <!-- This is the instruction that is currently being processed -->
1128    <xsl:variable name="instruction" select="."/>
1129
1130    <!-- Select all <node> elements that have a key that matches the k attribute of the text instruction -->
1131    <xsl:for-each select="$elements[name()='node'][tag[@k=$instruction/@k]]">
1132      <xsl:call-template name="renderText">
1133        <xsl:with-param name="instruction" select="$instruction"/>
1134      </xsl:call-template>
1135    </xsl:for-each>
1136
1137    <!-- Select all <way> elements -->
1138    <xsl:apply-templates select="$elements[name()='way']" mode="textPath">
1139      <xsl:with-param name="instruction" select="$instruction"/>
1140    </xsl:apply-templates>
1141  </xsl:template>
1142
1143
1144  <!-- Suppress output of any unhandled elements -->
1145  <xsl:template match="*" mode="textPath"/>
1146
1147
1148  <!-- Render textPaths for a way -->
1149  <xsl:template match="way" mode="textPath">
1150    <xsl:param name="instruction"/>
1151
1152    <!-- The current <way> element -->
1153    <xsl:variable name="way" select="."/>
1154
1155    <!-- DODI: !!!WORKAROUND!!! no text for one node ways-->
1156    <xsl:if test="count($way/nd) &gt; 1">
1157      <xsl:variable name='text'>
1158        <xsl:choose>
1159          <xsl:when test='$instruction/@k'>
1160            <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
1161          </xsl:when>
1162          <xsl:otherwise>
1163            <xsl:apply-templates select='$instruction' mode='textFormat'>
1164              <xsl:with-param name='way' select='$way'/>
1165            </xsl:apply-templates>
1166          </xsl:otherwise>
1167        </xsl:choose>
1168      </xsl:variable>
1169
1170      <xsl:if test='string($text)'>
1171
1172        <xsl:variable name="pathDirection">
1173          <xsl:choose>
1174            <!-- Manual override, reverse direction -->
1175            <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">reverse</xsl:when>
1176            <!-- Manual override, normal direction -->
1177            <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">normal</xsl:when>
1178            <!-- Automatic, reverse direction -->
1179            <xsl:when test="(key('nodeById',$way/nd[1]/@ref)/@lon &gt; key('nodeById',$way/nd[last()]/@ref)/@lon)">reverse</xsl:when>
1180            <!-- Automatic, normal direction -->
1181            <xsl:otherwise>normal</xsl:otherwise>
1182          </xsl:choose>
1183        </xsl:variable>
1184
1185        <xsl:variable name="wayPath">
1186          <xsl:choose>
1187            <!-- Normal -->
1188            <xsl:when test='$pathDirection="normal"'>
1189              <xsl:value-of select="concat('way_normal_',@id)"/>
1190            </xsl:when>
1191            <!-- Reverse -->
1192            <xsl:otherwise>
1193              <xsl:value-of select="concat('way_reverse_',@id)"/>
1194            </xsl:otherwise>
1195          </xsl:choose>
1196        </xsl:variable>
1197
1198        <xsl:call-template name="renderTextPath">
1199          <xsl:with-param name="instruction" select="$instruction"/>
1200          <xsl:with-param name="pathId" select="$wayPath"/>
1201          <xsl:with-param name="pathDirection" select="$pathDirection"/>
1202          <xsl:with-param name="text" select="$text"/>
1203        </xsl:call-template>
1204      </xsl:if>
1205    </xsl:if>
1206  </xsl:template>
1207
1208  <!-- Process extended form of text instruction -->
1209  <xsl:template match='text' mode='textFormat'>
1210    <xsl:param name='way'/>
1211
1212    <xsl:apply-templates mode='textFormat'>
1213      <xsl:with-param name='way' select='$way'/>
1214    </xsl:apply-templates>
1215  </xsl:template>
1216
1217
1218  <!-- Substitute a tag in a text instruction -->
1219  <xsl:template match='text/tag' mode='textFormat'>
1220    <xsl:param name='way'/>
1221
1222    <xsl:variable name='key' select='@k'/>
1223    <xsl:variable name='value'>
1224      <xsl:choose>
1225        <xsl:when test='$key="osm:user"'>
1226          <xsl:value-of select='$way/@user'/>
1227        </xsl:when>
1228        <xsl:when test='$key="osm:timestamp"'>
1229          <xsl:value-of select='$way/@timestamp'/>
1230        </xsl:when>
1231        <xsl:when test='$key="osm:id"'>
1232          <xsl:value-of select='$way/@id'/>
1233        </xsl:when>
1234        <xsl:otherwise>
1235          <xsl:value-of select='$way/tag[@k=$key]/@v'/>
1236        </xsl:otherwise>
1237      </xsl:choose>
1238    </xsl:variable>
1239    <xsl:choose>
1240      <xsl:when test='string($value)'>
1241        <xsl:value-of select='$value'/>
1242      </xsl:when>
1243      <xsl:otherwise>
1244        <xsl:value-of select='@default'/>
1245      </xsl:otherwise>
1246    </xsl:choose>
1247  </xsl:template>
1248
1249
1250
1251  <!-- Generate a way path for the current way element -->
1252  <xsl:template name="generateWayPaths">
1253    <!-- DODI: !!!WORKAROUND!!! skip one node ways -->
1254    <xsl:if test="count(nd) &gt; 1">
1255
1256      <!-- Generate a normal way path -->
1257      <xsl:variable name="pathWayNormal">
1258        <xsl:call-template name="generateWayPathNormal"/>
1259      </xsl:variable>
1260      <xsl:if test="$pathWayNormal!=''">
1261        <path id="way_normal_{@id}" d="{$pathWayNormal}"/>
1262      </xsl:if>
1263
1264      <!-- Generate a normal way path as area -->
1265      <!-- DODI: !!!WORKAROUND!!! added to generate "area for all ways, yes it is very dirty... but -->
1266      <!-- DODI: removed because of line2curves.pl duplicate node detection problem -->
1267      <!-- <xsl:variable name="pathArea">
1268      <xsl:call-template name="generateAreaPath"/>
1269    </xsl:variable>
1270    <path id="area_{@id}" d="{$pathArea}"/> -->
1271      <!-- Generate a reverse way path (if needed) -->
1272      <xsl:variable name="pathWayReverse">
1273        <xsl:choose>
1274          <!-- Manual override, reverse direction -->
1275          <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">
1276            <xsl:call-template name="generateWayPathReverse"/>
1277          </xsl:when>
1278          <!-- Manual override, normal direction -->
1279          <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">
1280            <!-- Generate nothing -->
1281          </xsl:when>
1282          <!-- Automatic, reverse direction -->
1283          <xsl:when test="(key('nodeById',nd[1]/@ref)/@lon &gt; key('nodeById',nd[last()]/@ref)/@lon)">
1284            <xsl:call-template name="generateWayPathReverse"/>
1285          </xsl:when>
1286        </xsl:choose>
1287      </xsl:variable>
1288      <xsl:if test="$pathWayReverse!=''">
1289        <path id="way_reverse_{@id}" d="{$pathWayReverse}"/>
1290      </xsl:if>
1291
1292      <!-- Generate the start, middle and end paths needed for smart-linecaps (TM). -->
1293      <xsl:variable name="pathWayStart">
1294        <xsl:call-template name="generatePathWayStart"/>
1295      </xsl:variable>
1296      <path id="way_start_{@id}" d="{$pathWayStart}"/>
1297
1298      <xsl:if test="count(nd) &gt; 1">
1299        <xsl:variable name="pathWayMid">
1300          <xsl:call-template name="generatePathWayMid"/>
1301        </xsl:variable>
1302        <path id="way_mid_{@id}" d="{$pathWayMid}"/>
1303      </xsl:if>
1304
1305      <xsl:variable name="pathWayEnd">
1306        <xsl:call-template name="generatePathWayEnd"/>
1307      </xsl:variable>
1308      <path id="way_end_{@id}" d="{$pathWayEnd}"/>
1309    </xsl:if >
1310  </xsl:template>
1311
1312
1313  <!-- Generate a normal way path -->
1314  <xsl:template name="generateWayPathNormal">
1315    <xsl:for-each select="nd">
1316      <xsl:choose>
1317        <xsl:when test="position()=1">
1318          <xsl:call-template name="moveToNode">
1319            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1320          </xsl:call-template>
1321        </xsl:when>
1322        <xsl:otherwise>
1323          <xsl:call-template name="lineToNode">
1324            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1325          </xsl:call-template>
1326        </xsl:otherwise>
1327      </xsl:choose>
1328    </xsl:for-each>
1329  </xsl:template>
1330
1331
1332  <!-- Generate a reverse way path -->
1333  <xsl:template name="generateWayPathReverse">
1334    <xsl:for-each select="nd">
1335      <xsl:sort select="position()" data-type="number" order="descending"/>
1336      <xsl:choose>
1337        <xsl:when test="position()=1">
1338          <xsl:call-template name="moveToNode">
1339            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1340          </xsl:call-template>
1341        </xsl:when>
1342        <xsl:otherwise>
1343          <xsl:call-template name="lineToNode">
1344            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1345          </xsl:call-template>
1346        </xsl:otherwise>
1347      </xsl:choose>
1348    </xsl:for-each>
1349  </xsl:template>
1350
1351
1352  <!-- These template generates two paths, one for each end of a way.  The line to the first node is cut in two so that the join
1353         between the two paths is not at an angle.  -->
1354  <xsl:template name="generatePathWayStart">
1355    <xsl:call-template name="moveToNode">
1356      <xsl:with-param name="node" select="key('nodeById',nd[1]/@ref)"/>
1357    </xsl:call-template>
1358    <xsl:call-template name="lineToMidpointPlus">
1359      <xsl:with-param name="fromNode" select="key('nodeById',nd[1]/@ref)"/>
1360      <xsl:with-param name="toNode" select="key('nodeById',nd[2]/@ref)"/>
1361    </xsl:call-template>
1362  </xsl:template>
1363
1364
1365  <xsl:template name="generatePathWayEnd">
1366    <xsl:call-template name="moveToNode">
1367      <xsl:with-param name="node" select="key('nodeById',nd[position()=last()]/@ref)"/>
1368    </xsl:call-template>
1369    <xsl:call-template name="lineToMidpointMinus">
1370      <xsl:with-param name="fromNode" select="key('nodeById',nd[position()=(last()-1)]/@ref)"/>
1371      <xsl:with-param name="toNode" select="key('nodeById',nd[position()=last()]/@ref)"/>
1372    </xsl:call-template>
1373  </xsl:template>
1374
1375  <xsl:template name="generatePathWayMid">
1376    <xsl:for-each select="nd">
1377      <xsl:choose>
1378        <xsl:when test="position()=1">
1379          <xsl:call-template name="moveToMidpointPlus">
1380            <xsl:with-param name="fromNode" select="key('nodeById',@ref)"/>
1381            <xsl:with-param name="toNode" select="key('nodeById',following-sibling::nd[1]/@ref)"/>
1382          </xsl:call-template>
1383        </xsl:when>
1384        <xsl:when test="position()=last()">
1385          <xsl:call-template name="lineToMidpointMinus">
1386            <xsl:with-param name="fromNode" select="key('nodeById',preceding-sibling::nd[1]/@ref)"/>
1387            <xsl:with-param name="toNode" select="key('nodeById',@ref)"/>
1388          </xsl:call-template>
1389        </xsl:when>
1390        <xsl:otherwise>
1391          <xsl:call-template name="lineToNode">
1392            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1393          </xsl:call-template>
1394        </xsl:otherwise>
1395      </xsl:choose>
1396    </xsl:for-each>
1397  </xsl:template>
1398
1399
1400
1401  <!-- Generate an area path for the current way or area element -->
1402  <xsl:template name="generateAreaPath">
1403    <xsl:variable name='relation' select="key('relationByWay',@id)[tag[@k='type' and @v='multipolygon']]"/>
1404
1405    <xsl:choose>
1406      <xsl:when test='$relation'>
1407        <xsl:message>
1408          <xsl:value-of select='$relation/@id'/>
1409        </xsl:message>
1410        <xsl:for-each select="$relation/member[@type='way']">
1411          <xsl:call-template name='generateAreaSubPath'>
1412            <xsl:with-param name='way' select="key('wayById',@ref)"/>
1413            <xsl:with-param name='position' select="position()"/>
1414          </xsl:call-template>
1415        </xsl:for-each>
1416        <xsl:text>Z</xsl:text>
1417      </xsl:when>
1418      <xsl:otherwise>
1419        <xsl:call-template name='generateAreaSubPath'>
1420          <xsl:with-param name='way' select='.'/>
1421          <xsl:with-param name='position' select="'1'"/>
1422        </xsl:call-template>
1423        <xsl:text>Z</xsl:text>
1424      </xsl:otherwise>
1425    </xsl:choose>
1426  </xsl:template>
1427
1428
1429  <xsl:template name='generateAreaSubPath'>
1430    <xsl:param name='way'/>
1431    <xsl:param name='position'/>
1432
1433    <xsl:variable name='loop' select='$way/nd[1]/@ref=$way/nd[last()]/@ref'/>
1434    <xsl:message>
1435      WayId: <xsl:value-of select='$way/@id'/>
1436      Loop: <xsl:value-of select='$loop'/>
1437      Loop: <xsl:value-of select='$way/nd[1]/@ref'/>
1438      Loop: <xsl:value-of select='$way/nd[last()]/@ref'/>
1439    </xsl:message>
1440    <xsl:for-each select="$way/nd">
1441      <xsl:choose>
1442        <xsl:when test="position()=1 and $loop">
1443          <xsl:if test='not($position=1)'>
1444            <xsl:text>Z</xsl:text>
1445          </xsl:if>
1446          <xsl:call-template name="moveToNode">
1447            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1448          </xsl:call-template>
1449        </xsl:when>
1450        <xsl:when test="$position=1 and position()=1 and not($loop=1)">
1451          <xsl:call-template name="moveToNode">
1452            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1453          </xsl:call-template>
1454        </xsl:when>
1455        <xsl:otherwise>
1456          <xsl:call-template name="lineToNode">
1457            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1458          </xsl:call-template>
1459        </xsl:otherwise>
1460      </xsl:choose>
1461    </xsl:for-each>
1462
1463
1464  </xsl:template>
1465
1466  <!-- Generate a MoveTo command for a node -->
1467  <xsl:template name="moveToNode">
1468    <xsl:param name='node' />
1469    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1470    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1471    <xsl:text>M</xsl:text>
1472    <xsl:value-of select="$x1"/>
1473    <xsl:text> </xsl:text>
1474    <xsl:value-of select="$y1"/>
1475  </xsl:template>
1476
1477  <!-- Generate a LineTo command for a nd -->
1478  <xsl:template name="lineToNode">
1479    <xsl:param name='node'/>
1480
1481    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1482    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1483    <xsl:text>L</xsl:text>
1484    <xsl:value-of select="$x1"/>
1485    <xsl:text> </xsl:text>
1486    <xsl:value-of select="$y1"/>
1487  </xsl:template>
1488
1489  <xsl:template name="lineToMidpointPlus">
1490    <xsl:param name='fromNode'/>
1491    <xsl:param name='toNode'/>
1492
1493    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1494    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1495
1496    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1497    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1498
1499    <xsl:text>L</xsl:text>
1500    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1501    <xsl:text> </xsl:text>
1502    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1503  </xsl:template>
1504
1505  <xsl:template name="lineToMidpointMinus">
1506    <xsl:param name='fromNode'/>
1507    <xsl:param name='toNode'/>
1508
1509    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1510    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1511
1512    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1513    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1514    <xsl:text>L</xsl:text>
1515    <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
1516    <xsl:text> </xsl:text>
1517    <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
1518  </xsl:template>
1519
1520
1521  <xsl:template name="moveToMidpointPlus">
1522    <xsl:param name='fromNode'/>
1523    <xsl:param name='toNode'/>
1524
1525    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1526    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1527
1528    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1529    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1530    <xsl:text>M</xsl:text>
1531    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1532    <xsl:text> </xsl:text>
1533    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1534  </xsl:template>
1535
1536  <!-- Some attribute shouldn't be copied -->
1537  <xsl:template match="@type|@ref|@scale|@smart-linecap" mode="copyAttributes" />
1538
1539  <!-- Copy all other attributes  -->
1540  <xsl:template match="@*" mode="copyAttributes">
1541    <xsl:copy/>
1542  </xsl:template>
1543
1544
1545  <!-- Rule processing engine -->
1546
1547  <!--
1548
1549                Calls all templates inside <rule> tags (including itself, if there are nested rules).
1550
1551                If the global var withOSMLayers is 'no', we don't care about layers and draw everything
1552                in one go. This is faster and is sometimes useful. For normal maps you want withOSMLayers
1553                to be 'yes', which is the default.
1554
1555        -->
1556  <xsl:template name="processRules">
1557
1558    <!-- First select all elements - exclude those marked as deleted by JOSM -->
1559    <xsl:variable name='elements' select="$data/osm/*[not(@action) or not(@action='delete')]" />
1560
1561    <xsl:choose>
1562
1563      <!-- Process all the rules, one layer at a time -->
1564      <xsl:when test="$withOSMLayers='yes'">
1565        <xsl:call-template name="processLayer">
1566          <xsl:with-param name="layer" select="'-5'"/>
1567          <xsl:with-param name="elements" select="$elements"/>
1568        </xsl:call-template>
1569        <xsl:call-template name="processLayer">
1570          <xsl:with-param name="layer" select="'-4'"/>
1571          <xsl:with-param name="elements" select="$elements"/>
1572        </xsl:call-template>
1573        <xsl:call-template name="processLayer">
1574          <xsl:with-param name="layer" select="'-3'"/>
1575          <xsl:with-param name="elements" select="$elements"/>
1576        </xsl:call-template>
1577        <xsl:call-template name="processLayer">
1578          <xsl:with-param name="layer" select="'-2'"/>
1579          <xsl:with-param name="elements" select="$elements"/>
1580        </xsl:call-template>
1581        <xsl:call-template name="processLayer">
1582          <xsl:with-param name="layer" select="'-1'"/>
1583          <xsl:with-param name="elements" select="$elements"/>
1584        </xsl:call-template>
1585        <xsl:call-template name="processLayer">
1586          <xsl:with-param name="layer" select="'0'"/>
1587          <xsl:with-param name="elements" select="$elements"/>
1588        </xsl:call-template>
1589        <xsl:call-template name="processLayer">
1590          <xsl:with-param name="layer" select="'1'"/>
1591          <xsl:with-param name="elements" select="$elements"/>
1592        </xsl:call-template>
1593        <xsl:call-template name="processLayer">
1594          <xsl:with-param name="layer" select="'2'"/>
1595          <xsl:with-param name="elements" select="$elements"/>
1596        </xsl:call-template>
1597        <xsl:call-template name="processLayer">
1598          <xsl:with-param name="layer" select="'3'"/>
1599          <xsl:with-param name="elements" select="$elements"/>
1600        </xsl:call-template>
1601        <xsl:call-template name="processLayer">
1602          <xsl:with-param name="layer" select="'4'"/>
1603          <xsl:with-param name="elements" select="$elements"/>
1604        </xsl:call-template>
1605        <xsl:call-template name="processLayer">
1606          <xsl:with-param name="layer" select="'5'"/>
1607          <xsl:with-param name="elements" select="$elements"/>
1608        </xsl:call-template>
1609      </xsl:when>
1610
1611      <!-- Process all the rules, without looking at the layers -->
1612      <xsl:otherwise>
1613        <xsl:apply-templates select="/rules/rule">
1614          <xsl:with-param name="elements" select="$elements"/>
1615          <xsl:with-param name="layer" select="'0'"/>
1616        </xsl:apply-templates>
1617      </xsl:otherwise>
1618
1619    </xsl:choose>
1620  </xsl:template>
1621
1622
1623  <xsl:template name="processLayer">
1624    <xsl:param name="layer"/>
1625    <xsl:param name="elements"/>
1626
1627    <g inkscape:groupmode="layer" id="layer{$layer}" inkscape:label="Layer {$layer}">
1628      <xsl:apply-templates select="/rules/rule">
1629        <xsl:with-param name="elements" select="$elements"/>
1630        <xsl:with-param name="layer" select="$layer"/>
1631      </xsl:apply-templates>
1632    </g>
1633  </xsl:template>
1634
1635
1636  <!-- Process a rule at a specific level -->
1637  <xsl:template match='rule'>
1638    <xsl:param name="elements"/>
1639    <xsl:param name="layer"/>
1640
1641    <!-- If the rule is for a specific layer and we are processing that layer then pass *all* elements
1642                     to the rule, otherwise just select the matching elements for this layer. -->
1643    <xsl:choose>
1644      <xsl:when test='$layer=@layer'>
1645        <xsl:call-template name="rule">
1646          <xsl:with-param name="elements" select="$elements"/>
1647          <xsl:with-param name="layer" select="$layer"/>
1648        </xsl:call-template>
1649      </xsl:when>
1650      <xsl:otherwise>
1651        <xsl:if test='not(@layer)'>
1652          <xsl:call-template name="rule">
1653            <xsl:with-param name="elements" select="$elements[
1654                                                        tag[@k='layer' and @v=$layer]
1655                                                        or ($layer='0' and count(tag[@k='layer'])=0)
1656                                                ]"/>
1657            <xsl:with-param name="layer" select="$layer"/>
1658          </xsl:call-template>
1659        </xsl:if>
1660      </xsl:otherwise>
1661    </xsl:choose>
1662  </xsl:template>
1663
1664
1665  <xsl:template name='rule'>
1666    <xsl:param name="elements"/>
1667    <xsl:param name="layer"/>
1668
1669    <!-- This is the rule currently being processed -->
1670    <xsl:variable name="rule" select="."/>
1671
1672    <!-- Make list of elements that this rule should be applied to -->
1673    <xsl:variable name="eBare">
1674      <xsl:choose>
1675        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
1676        <xsl:when test="$rule/@e">
1677          <xsl:value-of select="$rule/@e"/>
1678        </xsl:when>
1679        <xsl:otherwise>node|way</xsl:otherwise>
1680      </xsl:choose>
1681    </xsl:variable>
1682
1683    <!-- List of keys that this rule should be applied to -->
1684    <xsl:variable name="kBare" select="$rule/@k"/>
1685
1686    <!-- List of values that this rule should be applied to -->
1687    <xsl:variable name="vBare" select="$rule/@v"/>
1688    <xsl:variable name="sBare" select="$rule/@s"/>
1689
1690    <!-- Top'n'tail selectors with | for contains usage -->
1691    <xsl:variable name="e">
1692      |<xsl:value-of select="$eBare"/>|
1693    </xsl:variable>
1694    <xsl:variable name="k">
1695      |<xsl:value-of select="$kBare"/>|
1696    </xsl:variable>
1697    <xsl:variable name="v">
1698      |<xsl:value-of select="$vBare"/>|
1699    </xsl:variable>
1700    <xsl:variable name="s">
1701      |<xsl:value-of select="$sBare"/>|
1702    </xsl:variable>
1703
1704    <xsl:variable
1705      name="selectedElements"
1706      select="$elements[contains($e,concat('|',name(),'|'))
1707            or
1708            (contains($e,'|node|') and name()='way' and key('wayByNode',@id))
1709            ]"/>
1710
1711
1712    <!-- Patch $s -->
1713    <xsl:choose>
1714      <!-- way selector -->
1715      <xsl:when test="contains($s,'|way|')">
1716        <xsl:choose>
1717          <!-- every key -->
1718          <xsl:when test="contains($k,'|*|')">
1719            <xsl:choose>
1720              <!-- every key ,no value defined -->
1721              <xsl:when test="contains($v,'|~|')">
1722                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)=0]"/>
1723                <xsl:call-template name="processElements">
1724                  <xsl:with-param name="eBare" select="$eBare"/>
1725                  <xsl:with-param name="kBare" select="$kBare"/>
1726                  <xsl:with-param name="vBare" select="$vBare"/>
1727                  <xsl:with-param name="layer" select="$layer"/>
1728                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1729                  <xsl:with-param name="rule" select="$rule"/>
1730                </xsl:call-template>
1731              </xsl:when>
1732              <!-- every key ,every value -->
1733              <xsl:when test="contains($v,'|*|')">
1734                <xsl:variable name="allElements" select="$selectedElements"/>
1735                <xsl:call-template name="processElements">
1736                  <xsl:with-param name="eBare" select="$eBare"/>
1737                  <xsl:with-param name="kBare" select="$kBare"/>
1738                  <xsl:with-param name="vBare" select="$vBare"/>
1739                  <xsl:with-param name="layer" select="$layer"/>
1740                  <xsl:with-param name="elements" select="$allElements"/>
1741                  <xsl:with-param name="rule" select="$rule"/>
1742                </xsl:call-template>
1743              </xsl:when>
1744              <!-- every key , selected values -->
1745              <xsl:otherwise>
1746                <xsl:variable name="allElementsWithValue" select="$selectedElements[key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))]]"/>
1747                <xsl:call-template name="processElements">
1748                  <xsl:with-param name="eBare" select="$eBare"/>
1749                  <xsl:with-param name="kBare" select="$kBare"/>
1750                  <xsl:with-param name="vBare" select="$vBare"/>
1751                  <xsl:with-param name="layer" select="$layer"/>
1752                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1753                  <xsl:with-param name="rule" select="$rule"/>
1754                </xsl:call-template>
1755              </xsl:otherwise>
1756            </xsl:choose>
1757          </xsl:when>
1758          <!-- no value  -->
1759          <xsl:when test="contains($v,'|~|')">
1760            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])=0]"/>
1761            <xsl:call-template name="processElements">
1762              <xsl:with-param name="eBare" select="$eBare"/>
1763              <xsl:with-param name="kBare" select="$kBare"/>
1764              <xsl:with-param name="vBare" select="$vBare"/>
1765              <xsl:with-param name="layer" select="$layer"/>
1766              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1767              <xsl:with-param name="rule" select="$rule"/>
1768            </xsl:call-template>
1769          </xsl:when>
1770          <!-- every value  -->
1771          <xsl:when test="contains($v,'|*|')">
1772            <xsl:variable name="allElementsWithKey" select="$selectedElements[key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))]]"/>
1773            <xsl:call-template name="processElements">
1774              <xsl:with-param name="eBare" select="$eBare"/>
1775              <xsl:with-param name="kBare" select="$kBare"/>
1776              <xsl:with-param name="vBare" select="$vBare"/>
1777              <xsl:with-param name="layer" select="$layer"/>
1778              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1779              <xsl:with-param name="rule" select="$rule"/>
1780            </xsl:call-template>
1781          </xsl:when>
1782
1783          <!-- defined key and defined value -->
1784          <xsl:otherwise>
1785            <xsl:variable name="elementsWithKey" select="$selectedElements[
1786                                                        key('wayByNode',@id)/tag[
1787                                                                contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
1788                                                                ]
1789                                                        ]"/>
1790            <xsl:call-template name="processElements">
1791              <xsl:with-param name="eBare" select="$eBare"/>
1792              <xsl:with-param name="kBare" select="$kBare"/>
1793              <xsl:with-param name="vBare" select="$vBare"/>
1794              <xsl:with-param name="layer" select="$layer"/>
1795              <xsl:with-param name="elements" select="$elementsWithKey"/>
1796              <xsl:with-param name="rule" select="$rule"/>
1797            </xsl:call-template>
1798          </xsl:otherwise>
1799        </xsl:choose>
1800      </xsl:when>
1801
1802      <!-- other selector -->
1803      <xsl:otherwise>
1804        <xsl:choose>
1805          <xsl:when test="contains($k,'|*|')">
1806            <xsl:choose>
1807              <xsl:when test="contains($v,'|~|')">
1808                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)=0]"/>
1809                <xsl:call-template name="processElements">
1810                  <xsl:with-param name="eBare" select="$eBare"/>
1811                  <xsl:with-param name="kBare" select="$kBare"/>
1812                  <xsl:with-param name="vBare" select="$vBare"/>
1813                  <xsl:with-param name="layer" select="$layer"/>
1814                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1815                  <xsl:with-param name="rule" select="$rule"/>
1816                </xsl:call-template>
1817              </xsl:when>
1818              <xsl:when test="contains($v,'|*|')">
1819                <xsl:variable name="allElements" select="$selectedElements"/>
1820                <xsl:call-template name="processElements">
1821                  <xsl:with-param name="eBare" select="$eBare"/>
1822                  <xsl:with-param name="kBare" select="$kBare"/>
1823                  <xsl:with-param name="vBare" select="$vBare"/>
1824                  <xsl:with-param name="layer" select="$layer"/>
1825                  <xsl:with-param name="elements" select="$allElements"/>
1826                  <xsl:with-param name="rule" select="$rule"/>
1827                </xsl:call-template>
1828              </xsl:when>
1829              <xsl:otherwise>
1830                <xsl:variable name="allElementsWithValue" select="$selectedElements[tag[contains($v,concat('|',@v,'|'))]]"/>
1831                <xsl:call-template name="processElements">
1832                  <xsl:with-param name="eBare" select="$eBare"/>
1833                  <xsl:with-param name="kBare" select="$kBare"/>
1834                  <xsl:with-param name="vBare" select="$vBare"/>
1835                  <xsl:with-param name="layer" select="$layer"/>
1836                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1837                  <xsl:with-param name="rule" select="$rule"/>
1838                </xsl:call-template>
1839              </xsl:otherwise>
1840            </xsl:choose>
1841          </xsl:when>
1842          <xsl:when test="contains($v,'|~|')">
1843            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])=0]"/>
1844            <xsl:call-template name="processElements">
1845              <xsl:with-param name="eBare" select="$eBare"/>
1846              <xsl:with-param name="kBare" select="$kBare"/>
1847              <xsl:with-param name="vBare" select="$vBare"/>
1848              <xsl:with-param name="layer" select="$layer"/>
1849              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1850              <xsl:with-param name="rule" select="$rule"/>
1851            </xsl:call-template>
1852          </xsl:when>
1853          <xsl:when test="contains($v,'|*|')">
1854            <xsl:variable name="allElementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|'))]]"/>
1855            <xsl:call-template name="processElements">
1856              <xsl:with-param name="eBare" select="$eBare"/>
1857              <xsl:with-param name="kBare" select="$kBare"/>
1858              <xsl:with-param name="vBare" select="$vBare"/>
1859              <xsl:with-param name="layer" select="$layer"/>
1860              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1861              <xsl:with-param name="rule" select="$rule"/>
1862            </xsl:call-template>
1863          </xsl:when>
1864          <xsl:otherwise>
1865            <xsl:variable name="elementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))]]"/>
1866            <xsl:call-template name="processElements">
1867              <xsl:with-param name="eBare" select="$eBare"/>
1868              <xsl:with-param name="kBare" select="$kBare"/>
1869              <xsl:with-param name="vBare" select="$vBare"/>
1870              <xsl:with-param name="layer" select="$layer"/>
1871              <xsl:with-param name="elements" select="$elementsWithKey"/>
1872              <xsl:with-param name="rule" select="$rule"/>
1873            </xsl:call-template>
1874          </xsl:otherwise>
1875        </xsl:choose>
1876      </xsl:otherwise>
1877    </xsl:choose>
1878  </xsl:template>
1879
1880
1881  <xsl:template match="else">
1882    <xsl:param name="elements"/>
1883    <xsl:param name="layer"/>
1884
1885    <!-- This is the previous rule that is being negated -->
1886    <!-- TODO: abort if no preceding rule element -->
1887    <xsl:variable name="rule" select="preceding-sibling::rule[1]"/>
1888
1889    <!-- Make list of elements that this rule should be applied to -->
1890    <xsl:variable name="eBare">
1891      <xsl:choose>
1892        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
1893        <xsl:when test="$rule/@e">
1894          <xsl:value-of select="$rule/@e"/>
1895        </xsl:when>
1896        <xsl:otherwise>node|way</xsl:otherwise>
1897      </xsl:choose>
1898    </xsl:variable>
1899
1900    <!-- List of keys that this rule should be applied to -->
1901    <xsl:variable name="kBare" select="$rule/@k"/>
1902
1903    <!-- List of values that this rule should be applied to -->
1904    <xsl:variable name="vBare" select="$rule/@v"/>
1905    <xsl:variable name="sBare" select="$rule/@s"/>
1906
1907
1908    <!-- Top'n'tail selectors with | for contains usage -->
1909    <xsl:variable name="e">
1910      |<xsl:value-of select="$eBare"/>|
1911    </xsl:variable>
1912    <xsl:variable name="k">
1913      |<xsl:value-of select="$kBare"/>|
1914    </xsl:variable>
1915    <xsl:variable name="v">
1916      |<xsl:value-of select="$vBare"/>|
1917    </xsl:variable>
1918    <xsl:variable name="s">
1919      |<xsl:value-of select="$sBare"/>|
1920    </xsl:variable>
1921
1922    <xsl:variable
1923      name="selectedElements"
1924      select="$elements[contains($e,concat('|',name(),'|'))
1925              or
1926              (contains($e,'|node|') and name()='way'and key('wayByNode',@id))
1927              ]"/>
1928
1929    <!-- Patch $s -->
1930    <xsl:choose>
1931      <xsl:when test="contains($s,'|way|')">
1932        <xsl:choose>
1933          <xsl:when test="contains($k,'|*|')">
1934            <xsl:choose>
1935              <xsl:when test="contains($v,'|~|')">
1936                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)!=0]"/>
1937                <xsl:call-template name="processElements">
1938                  <xsl:with-param name="eBare" select="$eBare"/>
1939                  <xsl:with-param name="kBare" select="$kBare"/>
1940                  <xsl:with-param name="vBare" select="$vBare"/>
1941                  <xsl:with-param name="layer" select="$layer"/>
1942                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1943                  <xsl:with-param name="rule" select="$rule"/>
1944                </xsl:call-template>
1945              </xsl:when>
1946              <xsl:when test="contains($v,'|*|')">
1947                <!-- no-op! -->
1948              </xsl:when>
1949              <xsl:otherwise>
1950                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))])]"/>
1951                <xsl:call-template name="processElements">
1952                  <xsl:with-param name="eBare" select="$eBare"/>
1953                  <xsl:with-param name="kBare" select="$kBare"/>
1954                  <xsl:with-param name="vBare" select="$vBare"/>
1955                  <xsl:with-param name="layer" select="$layer"/>
1956                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1957                  <xsl:with-param name="rule" select="$rule"/>
1958                </xsl:call-template>
1959              </xsl:otherwise>
1960            </xsl:choose>
1961          </xsl:when>
1962          <xsl:when test="contains($v,'|~|')">
1963            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])!=0]"/>
1964            <xsl:call-template name="processElements">
1965              <xsl:with-param name="eBare" select="$eBare"/>
1966              <xsl:with-param name="kBare" select="$kBare"/>
1967              <xsl:with-param name="vBare" select="$vBare"/>
1968              <xsl:with-param name="layer" select="$layer"/>
1969              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1970              <xsl:with-param name="rule" select="$rule"/>
1971            </xsl:call-template>
1972          </xsl:when>
1973          <xsl:when test="contains($v,'|*|')">
1974            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])]"/>
1975            <xsl:call-template name="processElements">
1976              <xsl:with-param name="eBare" select="$eBare"/>
1977              <xsl:with-param name="kBare" select="$kBare"/>
1978              <xsl:with-param name="vBare" select="$vBare"/>
1979              <xsl:with-param name="layer" select="$layer"/>
1980              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1981              <xsl:with-param name="rule" select="$rule"/>
1982            </xsl:call-template>
1983          </xsl:when>
1984          <xsl:otherwise>
1985            <xsl:variable name="elementsWithKey" select="$selectedElements[not(
1986                         key('wayByNode',@id)/tag[
1987                            contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
1988                            ]
1989                         )]"/>
1990            <xsl:call-template name="processElements">
1991              <xsl:with-param name="eBare" select="$eBare"/>
1992              <xsl:with-param name="kBare" select="$kBare"/>
1993              <xsl:with-param name="vBare" select="$vBare"/>
1994              <xsl:with-param name="layer" select="$layer"/>
1995              <xsl:with-param name="elements" select="$elementsWithKey"/>
1996              <xsl:with-param name="rule" select="$rule"/>
1997            </xsl:call-template>
1998          </xsl:otherwise>
1999        </xsl:choose>
2000      </xsl:when>
2001
2002      <xsl:otherwise>
2003        <!-- not contains $s -->
2004        <xsl:choose>
2005          <xsl:when test="contains($k,'|*|')">
2006            <xsl:choose>
2007              <xsl:when test="contains($v,'|~|')">
2008                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)!=0]"/>
2009                <xsl:call-template name="processElements">
2010                  <xsl:with-param name="eBare" select="$eBare"/>
2011                  <xsl:with-param name="kBare" select="$kBare"/>
2012                  <xsl:with-param name="vBare" select="$vBare"/>
2013                  <xsl:with-param name="layer" select="$layer"/>
2014                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2015                  <xsl:with-param name="rule" select="$rule"/>
2016                </xsl:call-template>
2017              </xsl:when>
2018              <xsl:when test="contains($v,'|*|')">
2019                <!-- no-op! -->
2020              </xsl:when>
2021              <xsl:otherwise>
2022                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(tag[contains($v,concat('|',@v,'|'))])]"/>
2023                <xsl:call-template name="processElements">
2024                  <xsl:with-param name="eBare" select="$eBare"/>
2025                  <xsl:with-param name="kBare" select="$kBare"/>
2026                  <xsl:with-param name="vBare" select="$vBare"/>
2027                  <xsl:with-param name="layer" select="$layer"/>
2028                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2029                  <xsl:with-param name="rule" select="$rule"/>
2030                </xsl:call-template>
2031              </xsl:otherwise>
2032            </xsl:choose>
2033          </xsl:when>
2034          <xsl:when test="contains($v,'|~|')">
2035            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2036            <xsl:call-template name="processElements">
2037              <xsl:with-param name="eBare" select="$eBare"/>
2038              <xsl:with-param name="kBare" select="$kBare"/>
2039              <xsl:with-param name="vBare" select="$vBare"/>
2040              <xsl:with-param name="layer" select="$layer"/>
2041              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2042              <xsl:with-param name="rule" select="$rule"/>
2043            </xsl:call-template>
2044          </xsl:when>
2045          <xsl:when test="contains($v,'|*|')">
2046            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|'))])]"/>
2047            <xsl:call-template name="processElements">
2048              <xsl:with-param name="eBare" select="$eBare"/>
2049              <xsl:with-param name="kBare" select="$kBare"/>
2050              <xsl:with-param name="vBare" select="$vBare"/>
2051              <xsl:with-param name="layer" select="$layer"/>
2052              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2053              <xsl:with-param name="rule" select="$rule"/>
2054            </xsl:call-template>
2055          </xsl:when>
2056          <xsl:otherwise>
2057            <xsl:variable name="elementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))])]"/>
2058            <xsl:call-template name="processElements">
2059              <xsl:with-param name="eBare" select="$eBare"/>
2060              <xsl:with-param name="kBare" select="$kBare"/>
2061              <xsl:with-param name="vBare" select="$vBare"/>
2062              <xsl:with-param name="layer" select="$layer"/>
2063              <xsl:with-param name="elements" select="$elementsWithKey"/>
2064              <xsl:with-param name="rule" select="$rule"/>
2065            </xsl:call-template>
2066          </xsl:otherwise>
2067        </xsl:choose>
2068      </xsl:otherwise>
2069    </xsl:choose>
2070  </xsl:template>
2071
2072
2073  <xsl:template name="processElements">
2074    <xsl:param name="eBare"/>
2075    <xsl:param name="kBare"/>
2076    <xsl:param name="vBare"/>
2077    <xsl:param name="layer"/>
2078    <xsl:param name="elements"/>
2079    <xsl:param name="rule"/>
2080
2081    <xsl:if test="$elements">
2082      <xsl:message>
2083        Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>" &gt;
2084        Matched by <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
2085      </xsl:message>
2086
2087      <xsl:apply-templates select="*">
2088        <xsl:with-param name="layer" select="$layer"/>
2089        <xsl:with-param name="elements" select="$elements"/>
2090        <xsl:with-param name="rule" select="$rule"/>
2091      </xsl:apply-templates>
2092    </xsl:if>
2093  </xsl:template>
2094
2095  <!-- Draw SVG layers -->
2096  <xsl:template match="layer">
2097    <xsl:param name="elements"/>
2098    <xsl:param name="layer"/>
2099    <xsl:param name="rule"/>
2100
2101    <xsl:message>
2102      Processing SVG layer: <xsl:value-of select="@name"/> (at OSM layer <xsl:value-of select="$layer"/>)
2103    </xsl:message>
2104
2105    <xsl:variable name="opacity">
2106      <xsl:if test="@opacity">
2107        <xsl:value-of select="concat('opacity:',@opacity,';')"/>
2108      </xsl:if>
2109    </xsl:variable>
2110
2111    <xsl:variable name="display">
2112      <xsl:if test="(@display='none') or (@display='off')">
2113        <xsl:text>display:none;</xsl:text>
2114      </xsl:if>
2115    </xsl:variable>
2116
2117    <g inkscape:groupmode="layer" id="{@name}-{$layer}" inkscape:label="{@name}">
2118      <xsl:if test="concat($opacity,$display)!=''">
2119        <xsl:attribute name="style">
2120          <xsl:value-of select="concat($opacity,$display)"/>
2121        </xsl:attribute>
2122      </xsl:if>
2123      <xsl:apply-templates select="*">
2124        <xsl:with-param name="layer" select="$layer"/>
2125        <xsl:with-param name="elements" select="$elements"/>
2126      </xsl:apply-templates>
2127    </g>
2128
2129  </xsl:template>
2130
2131
2132  <!-- Draw map border -->
2133  <xsl:template name="drawBorder">
2134    <!-- dasharray definitions here can be overridden in stylesheet -->
2135    <g id="border" inkscape:groupmode="layer" inkscape:label="Map Border">
2136      <line id="border-left-casing" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2137      <line id="border-top-casing" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2138      <line id="border-bottom-casing" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2139      <line id="border-right-casing" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2140
2141      <line id="border-left-core" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2142      <line id="border-top-core" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2143      <line id="border-bottom-core" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2144      <line id="border-right-core" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2145    </g>
2146  </xsl:template>
2147
2148
2149  <!-- Draw a grid over the map in 1km increments -->
2150  <xsl:template name="drawGrid">
2151    <g id="grid" inkscape:groupmode="layer" inkscape:label="Grid">
2152      <xsl:call-template name="drawGridHorizontals">
2153        <xsl:with-param name="line" select="'1'"/>
2154      </xsl:call-template>
2155      <xsl:call-template name="drawGridVerticals">
2156        <xsl:with-param name="line" select="'1'"/>
2157      </xsl:call-template>
2158    </g>
2159  </xsl:template>
2160
2161
2162  <xsl:template name="drawGridHorizontals">
2163    <xsl:param name="line"/>
2164    <xsl:if test="($line*$km) &lt; $documentHeight">
2165      <line id="grid-hori-{$line}" x1="0px" y1="{$line*$km}px" x2="{$documentWidth}px" y2="{$line*$km}px" class="map-grid-line"/>
2166      <xsl:call-template name="drawGridHorizontals">
2167        <xsl:with-param name="line" select="$line+1"/>
2168      </xsl:call-template>
2169    </xsl:if>
2170  </xsl:template>
2171
2172
2173  <xsl:template name="drawGridVerticals">
2174    <xsl:param name="line"/>
2175    <xsl:if test="($line*$km) &lt; $documentWidth">
2176      <line id="grid-vert-{$line}" x1="{$line*$km}px" y1="0px" x2="{$line*$km}px" y2="{$documentHeight}px" class="map-grid-line"/>
2177      <xsl:call-template name="drawGridVerticals">
2178        <xsl:with-param name="line" select="$line+1"/>
2179      </xsl:call-template>
2180    </xsl:if>
2181  </xsl:template>
2182
2183
2184  <!-- Draw map title -->
2185  <xsl:template name="drawTitle">
2186    <xsl:param name="title"/>
2187
2188    <xsl:variable name="x" select="$documentWidth div 2"/>
2189    <xsl:variable name="y" select="30"/>
2190
2191    <g id="marginalia-title" inkscape:groupmode="layer" inkscape:label="Title">
2192      <rect id="marginalia-title-background" x="0px" y="0px" height="{$marginaliaTopHeight - 5}px" width="{$documentWidth}px" class="map-title-background"/>
2193      <text id="marginalia-title-text" class="map-title" x="{$x}" y="{$y}">
2194        <xsl:value-of select="$title"/>
2195      </text>
2196    </g>
2197  </xsl:template>
2198
2199
2200  <!-- Draw an approximate scale in the bottom left corner of the map -->
2201  <xsl:template name="drawScale">
2202    <xsl:variable name="x1" select="14"/>
2203    <xsl:variable name="y1" select="round(($documentHeight)+((($bottomLeftLatitude)-(number($bottomLeftLatitude)))*10000*$scale*$projection))+28"/>
2204    <xsl:variable name="x2" select="$x1+$km"/>
2205    <xsl:variable name="y2" select="$y1"/>
2206
2207    <g id="marginalia-scale" inkscape:groupmode="layer" inkscape:label="Scale">
2208      <line id="marginalia-scale-casing" class="map-scale-casing" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2209
2210      <line id="marginalia-scale-core" class="map-scale-core" stroke-dasharray="{($km div 10)}" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2211
2212      <line id="marginalia-scale-bookend-from" class="map-scale-bookend" x1="{$x1}" y1="{$y1 + 2}" x2="{$x1}" y2="{$y1 - 10}"/>
2213
2214      <line id="marginalia-scale-bookend-to" class="map-scale-bookend" x1="{$x2}" y1="{$y2 + 2}" x2="{$x2}" y2="{$y2 - 10}"/>
2215
2216      <text id="marginalia-scale-text-from" class="map-scale-caption" x="{$x1}" y="{$y1 - 10}">0</text>
2217
2218      <text id="marginalia-scale-text-to" class="map-scale-caption" x="{$x2}" y="{$y2 - 10}">1km</text>
2219    </g>
2220  </xsl:template>
2221
2222
2223  <!-- Create a comment in SVG source code and RDF description of license -->
2224  <xsl:template name="metadata">
2225
2226    <xsl:comment>
2227
2228      Copyright (c) <xsl:value-of select="$year"/> OpenStreetMap
2229      www.openstreetmap.org
2230      This work is licensed under the
2231      Creative Commons Attribution-ShareAlike 2.0 License.
2232      http://creativecommons.org/licenses/by-sa/2.0/
2233
2234    </xsl:comment>
2235    <metadata id="metadata">
2236      <rdf:RDF xmlns="http://web.resource.org/cc/">
2237        <cc:Work rdf:about="">
2238          <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
2239          <dc:format>image/svg+xml</dc:format>
2240          <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
2241          <dc:title>
2242            <xsl:value-of select="$title"/>
2243          </dc:title>
2244          <dc:date>
2245            <xsl:value-of select="$date"/>
2246          </dc:date>
2247          <dc:source>http://www.openstreetmap.org/</dc:source>
2248        </cc:Work>
2249        <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
2250          <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
2251          <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
2252          <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
2253          <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
2254          <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
2255          <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
2256        </cc:License>
2257      </rdf:RDF>
2258    </metadata>
2259  </xsl:template>
2260
2261  <!-- Create a license logo and description in the image -->
2262  <xsl:template name="in-image-license">
2263    <xsl:param name="dx"/>
2264    <xsl:param name="dy"/>
2265
2266    <g id="license" inkscape:groupmode="layer" inkscape:label="Copyright" transform="translate({$dx},{$dy})">
2267      <style type="text/css">
2268        <![CDATA[
2269                .license-text {
2270                    text-anchor: left;
2271                    font-family: "DejaVu Sans",sans-serif;
2272                    font-size: 6px;
2273                    fill: black;
2274                }
2275            ]]>
2276      </style>
2277      <a id="license-cc-logo-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2278        <g id="license-cc-logo" transform="scale(0.5,0.5) translate(-604,-49)">
2279          <path id="path3817_2_" nodetypes="ccccccc" d="M
2280                    182.23532,75.39014 L 296.29928,75.59326 C
2281                    297.89303,75.59326 299.31686,75.35644 299.31686,78.77344 L
2282                    299.17721,116.34033 L 179.3569,116.34033 L
2283                    179.3569,78.63379 C 179.3569,76.94922 179.51999,75.39014
2284                    182.23532,75.39014 z " style="fill:#aab2ab"/>
2285          <g id="g5908_2_" transform="matrix(0.872921,0,0,0.872921,50.12536,143.2144)">
2286            <path id="path5906_2_" type="arc" cx="296.35416"
2287            cy="264.3577" ry="22.939548" rx="22.939548" d="M
2288                        187.20944,-55.6792 C 187.21502,-46.99896
2289                        180.18158,-39.95825 171.50134,-39.95212 C
2290                        162.82113,-39.94708 155.77929,-46.97998
2291                        155.77426,-55.66016 C 155.77426,-55.66687
2292                        155.77426,-55.67249 155.77426,-55.6792 C
2293                        155.76922,-64.36054 162.80209,-71.40125
2294                        171.48233,-71.40631 C 180.16367,-71.41193
2295                        187.20441,-64.37842 187.20944,-55.69824 C
2296                        187.20944,-55.69263 187.20944,-55.68591
2297                        187.20944,-55.6792 z " style="fill:white"/>
2298            <g id="g5706_2_" transform="translate(-289.6157,99.0653)">
2299              <path id="path5708_2_" d="M 473.88455,-167.54724 C
2300                            477.36996,-164.06128 479.11294,-159.79333
2301                            479.11294,-154.74451 C 479.11294,-149.69513
2302                            477.40014,-145.47303 473.9746,-142.07715 C
2303                            470.33929,-138.50055 466.04281,-136.71283
2304                            461.08513,-136.71283 C 456.18736,-136.71283
2305                            451.96526,-138.48544 448.42003,-142.03238 C
2306                            444.87419,-145.57819 443.10158,-149.81537
2307                            443.10158,-154.74451 C 443.10158,-159.6731
2308                            444.87419,-163.94049 448.42003,-167.54724 C
2309                            451.87523,-171.03375 456.09728,-172.77618
2310                            461.08513,-172.77618 C 466.13342,-172.77618
2311                            470.39914,-171.03375 473.88455,-167.54724 z M
2312                            450.76657,-165.20239 C 447.81982,-162.22601
2313                            446.34701,-158.7395 446.34701,-154.74005 C
2314                            446.34701,-150.7417 447.80529,-147.28485
2315                            450.72125,-144.36938 C 453.63778,-141.45288
2316                            457.10974,-139.99462 461.1383,-139.99462 C
2317                            465.16683,-139.99462 468.66848,-141.46743
2318                            471.64486,-144.41363 C 474.47076,-147.14947
2319                            475.88427,-150.59069 475.88427,-154.74005 C
2320                            475.88427,-158.85809 474.44781,-162.35297
2321                            471.57659,-165.22479 C 468.70595,-168.09546
2322                            465.22671,-169.53131 461.1383,-169.53131 C
2323                            457.04993,-169.53131 453.59192,-168.08813
2324                            450.76657,-165.20239 z M 458.52106,-156.49927 C
2325                            458.07074,-157.4809 457.39673,-157.9715
2326                            456.49781,-157.9715 C 454.90867,-157.9715
2327                            454.11439,-156.90198 454.11439,-154.763 C
2328                            454.11439,-152.62341 454.90867,-151.55389
2329                            456.49781,-151.55389 C 457.54719,-151.55389
2330                            458.29676,-152.07519 458.74647,-153.11901 L
2331                            460.94923,-151.94598 C 459.8993,-150.0805
2332                            458.32417,-149.14697 456.22374,-149.14697 C
2333                            454.60384,-149.14697 453.30611,-149.64367
2334                            452.33168,-150.63653 C 451.35561,-151.62994
2335                            450.86894,-152.99926 450.86894,-154.7445 C
2336                            450.86894,-156.46008 451.37123,-157.82159
2337                            452.37642,-158.83013 C 453.38161,-159.83806
2338                            454.63347,-160.34264 456.13423,-160.34264 C
2339                            458.35435,-160.34264 459.94407,-159.46776
2340                            460.90504,-157.71978 L 458.52106,-156.49927 z M
2341                            468.8844,-156.49927 C 468.43353,-157.4809
2342                            467.77292,-157.9715 466.90201,-157.9715 C
2343                            465.28095,-157.9715 464.46988,-156.90198
2344                            464.46988,-154.763 C 464.46988,-152.62341
2345                            465.28095,-151.55389 466.90201,-151.55389 C
2346                            467.95304,-151.55389 468.68918,-152.07519
2347                            469.10925,-153.11901 L 471.36126,-151.94598 C
2348                            470.31301,-150.0805 468.74007,-149.14697
2349                            466.64358,-149.14697 C 465.02587,-149.14697
2350                            463.73095,-149.64367 462.75711,-150.63653 C
2351                            461.78494,-151.62994 461.29773,-152.99926
2352                            461.29773,-154.7445 C 461.29773,-156.46008
2353                            461.79221,-157.82159 462.78061,-158.83013 C
2354                            463.76843,-159.83806 465.02588,-160.34264
2355                            466.55408,-160.34264 C 468.77027,-160.34264
2356                            470.35776,-159.46776 471.3154,-157.71978 L
2357                            468.8844,-156.49927 z "/>
2358            </g>
2359          </g>
2360          <path d="M 297.29639,74.91064 L 181.06688,74.91064 C
2361                    179.8203,74.91064 178.80614,75.92529 178.80614,77.17187 L
2362                    178.80614,116.66748 C 178.80614,116.94922
2363                    179.03466,117.17822 179.31639,117.17822 L
2364                    299.04639,117.17822 C 299.32813,117.17822
2365                    299.55713,116.94922 299.55713,116.66748 L
2366                    299.55713,77.17188 C 299.55713,75.92529 298.54297,74.91064
2367                    297.29639,74.91064 z M 181.06688,75.93213 L
2368                    297.29639,75.93213 C 297.97998,75.93213 298.53565,76.48828
2369                    298.53565,77.17188 C 298.53565,77.17188 298.53565,93.09131
2370                    298.53565,104.59034 L 215.4619,104.59034 C
2371                    212.41698,110.09571 206.55077,113.83399 199.81835,113.83399
2372                    C 193.083,113.83399 187.21825,110.09913 184.1748,104.59034
2373                    L 179.82666,104.59034 C 179.82666,93.09132
2374                    179.82666,77.17188 179.82666,77.17188 C 179.82664,76.48828
2375                    180.38329,75.93213 181.06688,75.93213 z " id="frame"/>
2376          <g enable-background="new" id="g2821">
2377            <path d="M 265.60986,112.8833 C 265.68994,113.03906
2378                        265.79736,113.16504 265.93115,113.26172 C
2379                        266.06494,113.35791 266.22119,113.42969
2380                        266.40088,113.47608 C 266.58154,113.52296
2381                        266.76807,113.54639 266.96045,113.54639 C
2382                        267.09033,113.54639 267.22998,113.53565
2383                        267.3794,113.51368 C 267.52784,113.4922
2384                        267.66749,113.44972 267.79835,113.3877 C
2385                        267.92823,113.32569 268.03761,113.23975
2386                        268.12355,113.13086 C 268.21144,113.02197
2387                        268.25441,112.88379 268.25441,112.71533 C
2388                        268.25441,112.53515 268.19679,112.38916
2389                        268.08156,112.27685 C 267.9673,112.16455
2390                        267.81594,112.07177 267.62941,111.99658 C
2391                        267.44386,111.92236 267.23195,111.85693
2392                        266.9966,111.80078 C 266.76027,111.74463
2393                        266.52101,111.68262 266.27883,111.61377 C
2394                        266.02981,111.55176 265.78762,111.47559
2395                        265.55129,111.38525 C 265.31594,111.29541
2396                        265.10402,111.17822 264.9175,111.03515 C
2397                        264.73098,110.89208 264.58059,110.71337
2398                        264.46535,110.49853 C 264.35109,110.28369
2399                        264.29347,110.02392 264.29347,109.71923 C
2400                        264.29347,109.37646 264.36671,109.07958
2401                        264.51222,108.82763 C 264.6587,108.57568
2402                        264.85011,108.36572 265.08644,108.19726 C
2403                        265.32179,108.02929 265.58937,107.90478
2404                        265.8882,107.82372 C 266.18605,107.74315
2405                        266.48488,107.70263 266.78273,107.70263 C
2406                        267.13136,107.70263 267.46535,107.74169
2407                        267.78566,107.81982 C 268.105,107.89746
2408                        268.39015,108.02392 268.6382,108.19824 C
2409                        268.88722,108.37256 269.08449,108.59521
2410                        269.23097,108.86621 C 269.37648,109.13721
2411                        269.44972,109.46582 269.44972,109.85156 L
2412                        268.02784,109.85156 C 268.01514,109.65234
2413                        267.97315,109.4873 267.90284,109.35693 C
2414                        267.83155,109.22607 267.73682,109.12353
2415                        267.61964,109.04834 C 267.50148,108.97412
2416                        267.36671,108.9209 267.21534,108.89014 C
2417                        267.063,108.85889 266.89796,108.84326
2418                        266.71827,108.84326 C 266.60108,108.84326
2419                        266.48292,108.85596 266.36573,108.88037 C
2420                        266.24757,108.90576 266.14112,108.94922
2421                        266.04542,109.01123 C 265.94874,109.07373
2422                        265.86964,109.15137 265.80812,109.24463 C
2423                        265.7466,109.33838 265.71535,109.45654
2424                        265.71535,109.59961 C 265.71535,109.73047
2425                        265.73976,109.83643 265.78957,109.91699 C
2426                        265.83937,109.99804 265.93801,110.07275
2427                        266.08352,110.14111 C 266.22903,110.20947
2428                        266.43118,110.27832 266.68899,110.34668 C
2429                        266.9468,110.41504 267.28372,110.50244
2430                        267.70071,110.60791 C 267.82473,110.63281
2431                        267.99661,110.67822 268.21731,110.74365 C
2432                        268.43801,110.80908 268.65676,110.91308
2433                        268.87454,111.05615 C 269.09231,111.1997
2434                        269.27981,111.39111 269.43899,111.63037 C
2435                        269.59719,111.87012 269.67629,112.17676
2436                        269.67629,112.55029 C 269.67629,112.85547
2437                        269.61672,113.13867 269.49856,113.3999 C
2438                        269.3804,113.66162 269.20461,113.8872
2439                        268.97122,114.07666 C 268.73782,114.26709
2440                        268.44876,114.41455 268.10403,114.52051 C
2441                        267.75833,114.62647 267.35794,114.6792
2442                        266.90481,114.6792 C 266.53762,114.6792
2443                        266.18118,114.63379 265.83547,114.54346 C
2444                        265.49074,114.45313 265.18508,114.31104
2445                        264.92043,114.11768 C 264.65676,113.92432
2446                        264.4468,113.67774 264.29055,113.37891 C
2447                        264.13528,113.07959 264.06106,112.7251
2448                        264.06692,112.31397 L 265.4888,112.31397 C
2449                        265.48877,112.53809 265.52881,112.72803
2450                        265.60986,112.8833 z " id="path2823"
2451            style="fill:white"/>
2452            <path d="M 273.8667,107.8667 L
2453                        276.35986,114.53076 L 274.8374,114.53076 L
2454                        274.33349,113.04638 L 271.84033,113.04638 L
2455                        271.31787,114.53076 L 269.84326,114.53076 L
2456                        272.36377,107.8667 L 273.8667,107.8667 z M
2457                        273.95068,111.95264 L 273.11084,109.50928 L
2458                        273.09229,109.50928 L 272.22315,111.95264 L
2459                        273.95068,111.95264 z " id="path2825"
2460            style="fill:white"/>
2461          </g>
2462          <g enable-background="new" id="g2827">
2463            <path d="M 239.17821,107.8667 C 239.49559,107.8667
2464                        239.78563,107.89502 240.04735,107.95068 C
2465                        240.30907,108.00683 240.53368,108.09863
2466                        240.72118,108.22607 C 240.9077,108.35351
2467                        241.05321,108.52295 241.15575,108.73437 C
2468                        241.25829,108.94579 241.31005,109.20703
2469                        241.31005,109.51806 C 241.31005,109.854
2470                        241.23388,110.13329 241.08056,110.35742 C
2471                        240.92822,110.58154 240.70165,110.76465
2472                        240.40283,110.90771 C 240.81494,111.02587
2473                        241.12256,111.23291 241.32568,111.5288 C
2474                        241.5288,111.82469 241.63037,112.18114
2475                        241.63037,112.59814 C 241.63037,112.93408
2476                        241.56494,113.22509 241.43408,113.47119 C
2477                        241.30322,113.7168 241.12646,113.91748
2478                        240.90576,114.07324 C 240.68408,114.229
2479                        240.43115,114.34424 240.14795,114.41845 C
2480                        239.86377,114.49365 239.57275,114.53075
2481                        239.27295,114.53075 L 236.03662,114.53075 L
2482                        236.03662,107.86669 L 239.17821,107.86669 L
2483                        239.17821,107.8667 z M 238.99071,110.56201 C
2484                        239.25243,110.56201 239.46727,110.5 239.63622,110.37597
2485                        C 239.80419,110.25146 239.88817,110.05029
2486                        239.88817,109.77099 C 239.88817,109.61572
2487                        239.85985,109.48828 239.80419,109.38915 C
2488                        239.74755,109.28954 239.67333,109.21239
2489                        239.57958,109.15624 C 239.48583,109.10058
2490                        239.37841,109.06151 239.25731,109.04003 C
2491                        239.13524,109.01806 239.00926,109.00732
2492                        238.8784,109.00732 L 237.50535,109.00732 L
2493                        237.50535,110.56201 L 238.99071,110.56201 z M
2494                        239.07664,113.39014 C 239.22019,113.39014
2495                        239.35691,113.37647 239.48777,113.34815 C
2496                        239.61863,113.32032 239.73484,113.27344
2497                        239.83445,113.2085 C 239.93406,113.14307
2498                        240.01316,113.0542 240.07273,112.94239 C
2499                        240.1323,112.83058 240.1616,112.68751
2500                        240.1616,112.51319 C 240.1616,112.17139
2501                        240.06492,111.92725 239.87156,111.78126 C
2502                        239.6782,111.63527 239.42234,111.56202
2503                        239.10496,111.56202 L 237.50535,111.56202 L
2504                        237.50535,113.39014 L 239.07664,113.39014 z "
2505            id="path2829" style="fill:white"/>
2506            <path d="M 241.88914,107.8667 L 243.53269,107.8667 L
2507                        245.09324,110.49854 L 246.64402,107.8667 L
2508                        248.27781,107.8667 L 245.80418,111.97315 L
2509                        245.80418,114.53077 L 244.33543,114.53077 L
2510                        244.33543,111.93604 L 241.88914,107.8667 z "
2511            id="path2831" style="fill:white"/>
2512          </g>
2513          <g id="g6316_1_" transform="matrix(0.624995,0,0,0.624995,391.2294,176.9332)">
2514            <path id="path6318_1_" type="arc" cx="475.97119"
2515            cy="252.08646" ry="29.209877" rx="29.209877" d="M
2516                        -175.0083,-139.1153 C -175.00204,-129.7035
2517                        -182.62555,-122.06751 -192.03812,-122.06049 C
2518                        -201.44913,-122.05341 -209.08512,-129.67774
2519                        -209.09293,-139.09028 C -209.09293,-139.09809
2520                        -209.09293,-139.10749 -209.09293,-139.1153 C
2521                        -209.09919,-148.52784 -201.47413,-156.1623
2522                        -192.06311,-156.17011 C -182.65054,-156.17713
2523                        -175.01456,-148.55207 -175.0083,-139.14026 C
2524                        -175.0083,-139.13092 -175.0083,-139.1239
2525                        -175.0083,-139.1153 z " style="fill:white"/>
2526            <g id="g6320_1_" transform="translate(-23.9521,-89.72962)">
2527              <path id="path6322_1_" d="M -168.2204,-68.05536 C
2528                            -173.39234,-68.05536 -177.76892,-66.25067
2529                            -181.35175,-62.64203 C -185.02836,-58.90759
2530                            -186.86588,-54.48883 -186.86588,-49.38568 C
2531                            -186.86588,-44.28253 -185.02836,-39.89416
2532                            -181.35175,-36.22308 C -177.67673,-32.55114
2533                            -173.29859,-30.71521 -168.2204,-30.71521 C
2534                            -163.07974,-30.71521 -158.62503,-32.56677
2535                            -154.85312,-36.26996 C -151.30307,-39.78558
2536                            -149.52652,-44.15827 -149.52652,-49.38568 C
2537                            -149.52652,-54.6123 -151.33432,-59.03265
2538                            -154.94843,-62.64203 C -158.5625,-66.25067
2539                            -162.98599,-68.05536 -168.2204,-68.05536 z M
2540                            -168.17352,-64.69519 C -163.936,-64.69519
2541                            -160.33752,-63.20221 -157.37655,-60.21466 C
2542                            -154.38748,-57.25836 -152.89214,-53.64899
2543                            -152.89214,-49.38568 C -152.89214,-45.09186
2544                            -154.35466,-41.52856 -157.28438,-38.69653 C
2545                            -160.36876,-35.64727 -163.99849,-34.12304
2546                            -168.17351,-34.12304 C -172.34856,-34.12304
2547                            -175.94701,-35.63244 -178.96892,-38.64965 C
2548                            -181.9908,-41.66918 -183.50176,-45.24657
2549                            -183.50176,-49.38567 C -183.50176,-53.52398
2550                            -181.97518,-57.13414 -178.92205,-60.21465 C
2551                            -175.9939,-63.20221 -172.41107,-64.69519
2552                            -168.17352,-64.69519 z "/>
2553              <path id="path6324_1_" d="M -176.49548,-52.02087 C
2554                            -175.75171,-56.71856 -172.44387,-59.22949
2555                            -168.30008,-59.22949 C -162.33911,-59.22949
2556                            -158.70783,-54.90448 -158.70783,-49.1372 C
2557                            -158.70783,-43.50982 -162.57194,-39.13793
2558                            -168.39383,-39.13793 C -172.39856,-39.13793
2559                            -175.98297,-41.60277 -176.63611,-46.43877 L
2560                            -171.93292,-46.43877 C -171.7923,-43.92778
2561                            -170.1626,-43.04418 -167.83447,-43.04418 C
2562                            -165.1813,-43.04418 -163.4563,-45.50908
2563                            -163.4563,-49.27709 C -163.4563,-53.22942
2564                            -164.94693,-55.32244 -167.74228,-55.32244 C
2565                            -169.79074,-55.32244 -171.55948,-54.57787
2566                            -171.93292,-52.02087 L -170.56418,-52.02789 L
2567                            -174.26734,-48.32629 L -177.96894,-52.02789 L
2568                            -176.49548,-52.02087 z "/>
2569            </g>
2570          </g>
2571          <g id="g2838">
2572            <circle cx="242.56226" cy="90.224609" r="10.8064" id="circle2840" style="fill:white"/>
2573            <g id="g2842">
2574              <path d="M 245.68994,87.09766 C 245.68994,86.68116
2575                            245.35205,86.34424 244.93603,86.34424 L
2576                            240.16357,86.34424 C 239.74755,86.34424
2577                            239.40966,86.68115 239.40966,87.09766 L
2578                            239.40966,91.87061 L 240.74071,91.87061 L
2579                            240.74071,97.52295 L 244.3579,97.52295 L
2580                            244.3579,91.87061 L 245.68993,91.87061 L
2581                            245.68993,87.09766 L 245.68994,87.09766 z "
2582              id="path2844"/>
2583              <circle cx="242.5498" cy="84.083008" r="1.63232" id="circle2846"/>
2584            </g>
2585            <path clip-rule="evenodd" d="M 242.53467,78.31836 C
2586                        239.30322,78.31836 236.56641,79.4458 234.32715,81.70215
2587                        C 232.0293,84.03516 230.88086,86.79736
2588                        230.88086,89.98633 C 230.88086,93.1753
2589                        232.0293,95.91846 234.32715,98.21338 C
2590                        236.625,100.50781 239.36133,101.65527
2591                        242.53467,101.65527 C 245.74756,101.65527
2592                        248.53272,100.49853 250.88819,98.18359 C
2593                        253.10889,95.98681 254.21827,93.2539 254.21827,89.98632
2594                        C 254.21827,86.71874 253.08936,83.95751
2595                        250.83057,81.70214 C 248.57178,79.4458
2596                        245.80615,78.31836 242.53467,78.31836 z M
2597                        242.56396,80.41797 C 245.2124,80.41797
2598                        247.46142,81.35156 249.31103,83.21875 C
2599                        251.18115,85.06592 252.11572,87.32227
2600                        252.11572,89.98633 C 252.11572,92.66992
2601                        251.20068,94.89746 249.36963,96.66699 C
2602                        247.4419,98.57275 245.17334,99.52539 242.56397,99.52539
2603                        C 239.9546,99.52539 237.70557,98.58252
2604                        235.81739,96.6958 C 233.92774,94.80957
2605                        232.98389,92.57324 232.98389,89.98633 C
2606                        232.98389,87.3999 233.93799,85.14404 235.84619,83.21875
2607                        C 237.67676,81.35156 239.9165,80.41797
2608                        242.56396,80.41797 z " id="path2848"
2609            style="fill-rule:evenodd"/>
2610          </g>
2611        </g>
2612      </a>
2613      <a id="license-osm-link" xlink:href="http://www.openstreetmap.org/">
2614        <g transform="translate(-210,10)" id="license-osm-text">
2615          <text class="license-text" dx="0" dy="0">
2616            Copyright © <xsl:value-of select="$year"/> OpenStreetMap (openstreetmap.org)
2617          </text>
2618        </g>
2619      </a>
2620      <a id="license-cc-text-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2621        <g transform="translate(-150,18)" id="license-cc-text">
2622          <text class="license-text" dx="0" dy="0">This work is licensed under the Creative</text>
2623          <text class="license-text" dx="0" dy="8">Commons Attribution-ShareAlike 2.0 License.</text>
2624          <text class="license-text" dx="0" dy="16">http://creativecommons.org/licenses/by-sa/2.0/</text>
2625        </g>
2626      </a>
2627    </g>
2628  </xsl:template>
2629
2630
2631  <!-- Draw zoom controls -->
2632  <xsl:template name="zoomControl">
2633    <defs>
2634
2635      <style type="text/css">
2636        .fancyButton {
2637        stroke: #8080ff;
2638        stroke-width: 2px;
2639        fill: #fefefe;
2640        }
2641        .fancyButton:hover {
2642        stroke: red;
2643        }
2644      </style>
2645
2646      <filter id="fancyButton" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="350">
2647        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
2648        <feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
2649        <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" specularExponent="20" lighting-color="white" result="specOut">
2650          <fePointLight x="-5000" y="-10000" z="7000"/>
2651        </feSpecularLighting>
2652        <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
2653        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
2654        <feMerge>
2655          <feMergeNode in="offsetBlur"/>
2656          <feMergeNode in="litPaint"/>
2657        </feMerge>
2658      </filter>
2659      <symbol id="panDown" viewBox="0 0 19 19" class="fancyButton">
2660        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2661        <path d="M 9.5,5 L 9.5,14"/>
2662      </symbol>
2663      <symbol id="panUp" viewBox="0 0 19 19" class="fancyButton">
2664        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2665        <path d="M 9.5,5 L 9.5,14"/>
2666      </symbol>
2667      <symbol id="panLeft" viewBox="0 0 19 19" class="fancyButton">
2668        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2669        <path d="M 5,9.5 L 14,9.5"/>
2670      </symbol>
2671      <symbol id="panRight" viewBox="0 0 19 19" class="fancyButton">
2672        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2673        <path d="M 5,9.5 L 14,9.5"/>
2674      </symbol>
2675      <symbol id="zoomIn" viewBox="0 0 19 19" class="fancyButton">
2676        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2677        <path d="M 5,9.5 L 14,9.5 M 9.5,5 L 9.5,14"/>
2678      </symbol>
2679      <symbol id="zoomOut" viewBox="0 0 19 19" class="fancyButton">
2680        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2681        <path d="M 5,9.5 L 14,9.5"/>
2682      </symbol>
2683
2684    </defs>
2685
2686    <g id="gPanDown" filter="url(#fancyButton)" onclick="fnPan('down')">
2687      <use x="18px" y="60px" xlink:href="#panDown" width="14px" height="14px"/>
2688    </g>
2689    <g id="gPanRight" filter="url(#fancyButton)" onclick="fnPan('right')">
2690      <use x="8px" y="70px" xlink:href="#panRight" width="14px" height="14px"/>
2691    </g>
2692    <g id="gPanLeft" filter="url(#fancyButton)" onclick="fnPan('left')">
2693      <use x="28px" y="70px" xlink:href="#panLeft" width="14px" height="14px"/>
2694    </g>
2695    <g id="gPanUp" filter="url(#fancyButton)" onclick="fnPan('up')">
2696      <use x="18px" y="80px" xlink:href="#panUp" width="14px" height="14px"/>
2697    </g>
2698
2699    <xsl:variable name="x1" select="25"/>
2700    <xsl:variable name="y1" select="105"/>
2701    <xsl:variable name="x2" select="25"/>
2702    <xsl:variable name="y2" select="300"/>
2703
2704    <line style="stroke-width: 10; stroke-linecap: butt; stroke: #8080ff;">
2705      <xsl:attribute name="x1">
2706        <xsl:value-of select="$x1"/>
2707      </xsl:attribute>
2708      <xsl:attribute name="y1">
2709        <xsl:value-of select="$y1"/>
2710      </xsl:attribute>
2711      <xsl:attribute name="x2">
2712        <xsl:value-of select="$x2"/>
2713      </xsl:attribute>
2714      <xsl:attribute name="y2">
2715        <xsl:value-of select="$y2"/>
2716      </xsl:attribute>
2717    </line>
2718
2719    <line style="stroke-width: 8; stroke-linecap: butt; stroke: white; stroke-dasharray: 10,1;">
2720      <xsl:attribute name="x1">
2721        <xsl:value-of select="$x1"/>
2722      </xsl:attribute>
2723      <xsl:attribute name="y1">
2724        <xsl:value-of select="$y1"/>
2725      </xsl:attribute>
2726      <xsl:attribute name="x2">
2727        <xsl:value-of select="$x2"/>
2728      </xsl:attribute>
2729      <xsl:attribute name="y2">
2730        <xsl:value-of select="$y2"/>
2731      </xsl:attribute>
2732    </line>
2733
2734    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
2735    <g id="gZoomIn" filter="url(#fancyButton)" onmousedown="fnZoom('in')">
2736      <use x="15.5px" y="100px" xlink:href="#zoomIn" width="19px" height="19px"/>
2737    </g>
2738
2739    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
2740    <g id="gZoomOut" filter="url(#fancyButton)" onmousedown="fnZoom('out')">
2741      <use x="15.5px" y="288px" xlink:href="#zoomOut" width="19px" height="19px"/>
2742    </g>
2743  </xsl:template>
2744
2745  <xsl:template name="javaScript">
2746    <script>
2747      /*
2748
2749      Osmarender
2750
2751      interactive.js
2752
2753      */
2754
2755      function fnResize() {
2756      fnResizeElement("gAttribution")
2757      fnResizeElement("gLicense")
2758      fnResizeElement("gZoomIn")
2759      fnResizeElement("gZoomOut")
2760      }
2761
2762
2763      function fnResizeElement(e) {
2764      //
2765      var oSVG,scale,currentTranslateX,currentTranslateY,oe
2766      //
2767      oSVG=document.rootElement
2768      scale=1/oSVG.currentScale
2769      currentTranslateX=oSVG.currentTranslate.x
2770      currentTranslateY=oSVG.currentTranslate.y
2771      oe=document.getElementById(e)
2772      if (oe) oe.setAttributeNS(null,"transform","scale("+scale+","+scale+") translate("+(-currentTranslateX)+","+(-currentTranslateY)+")")
2773      }
2774
2775
2776      function fnToggleImage(osmImage) {
2777      var xlink = 'http://www.w3.org/1999/xlink';
2778      ogThumbnail=document.getElementById('gThumbnail')
2779      if (ogThumbnail.getAttributeNS(null,"visibility")=="visible") fnHideImage()
2780      else {
2781      ogThumbnail.setAttributeNS(null,"visibility","visible")
2782      oThumbnail=document.getElementById('thumbnail')
2783      oThumbnail.setAttributeNS(xlink,"href",osmImage)
2784      }
2785      }
2786
2787      function fnHideImage() {
2788      ogThumbnail=document.getElementById('gThumbnail')
2789      ogThumbnail.setAttributeNS(null,"visibility","hidden")
2790      }
2791
2792
2793      /* The following code originally written by Jonathan Watt (http://jwatt.org/), Aug. 2005 */
2794
2795      if (!window)
2796      window = this;
2797
2798
2799      function fnOnLoad(evt) {
2800      if (!document) window.document = evt.target.ownerDocument
2801      }
2802
2803
2804      /**
2805      * Event handlers to change the current user space for the zoom and pan
2806      * controls to make them appear to be scale invariant.
2807      */
2808
2809      function fnOnZoom(evt) {
2810      try {
2811      if (evt.newScale == undefined) throw 'bad interface'
2812      // update the transform list that adjusts for zoom and pan
2813      var tlist = document.getElementById('staticElements').transform.baseVal
2814      tlist.getItem(0).setScale(1/evt.newScale, 1/evt.newScale)
2815      tlist.getItem(1).setTranslate(-evt.newTranslate.x, -evt.newTranslate.y)
2816      }
2817      catch (e) {
2818      // work around difficiencies in non-moz implementations (some don't
2819      // implement the SVGZoomEvent or SVGAnimatedTransform interfaces)
2820      var de = document.documentElement
2821      var tform = 'scale(' + 1/de.currentScale + ') ' + 'translate(' + (-de.currentTranslate.x) + ', ' + (-de.currentTranslate.y) + ')'
2822      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
2823      }
2824      }
2825
2826
2827      function fnOnScroll(evt) {
2828      var ct = document.documentElement.currentTranslate
2829      try {
2830      // update the transform list that adjusts for zoom and pan
2831      var tlist = document.getElementById('staticElements').transform.baseVal
2832      tlist.getItem(1).setTranslate(-ct.x, -ct.y)
2833      }
2834      catch (e) {
2835      // work around difficiencies in non-moz implementations (some don't
2836      // implement the SVGAnimatedTransform interface)
2837      var tform = 'scale(' + 1/document.documentElement.currentScale + ') ' + 'translate(' + (-ct.x) + ', ' + (-ct.y) + ')';
2838      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
2839      }
2840      }
2841
2842
2843      function fnZoom(type) {
2844      var de = document.documentElement;
2845      var oldScale = de.currentScale;
2846      var oldTranslate = { x: de.currentTranslate.x, y: de.currentTranslate.y };
2847      var s = 2;
2848      if (type == 'in') {de.currentScale *= 1.5;}
2849      if (type == 'out') {de.currentScale /= 1.4;}
2850      // correct currentTranslate so zooming is to the center of the viewport:
2851
2852      var vp_width, vp_height;
2853      try {
2854      vp_width = de.viewport.width;
2855      vp_height = de.viewport.height;
2856      }
2857      catch (e) {
2858      // work around difficiency in moz ('viewport' property not implemented)
2859      vp_width = window.innerWidth;
2860      vp_height = window.innerHeight;
2861      }
2862      de.currentTranslate.x = vp_width/2 - ((de.currentScale/oldScale) * (vp_width/2 - oldTranslate.x));
2863      de.currentTranslate.y = vp_height/2 - ((de.currentScale/oldScale) * (vp_height/2 - oldTranslate.y));
2864
2865      }
2866
2867
2868      function fnPan(type) {
2869      var de = document.documentElement;
2870      var ct = de.currentTranslate;
2871      var t = 150;
2872      if (type == 'right') ct.x += t;
2873      if (type == 'down') ct.y += t;
2874      if (type == 'left') ct.x -= t;
2875      if (type == 'up') ct.y -= t;
2876      }
2877
2878
2879      var gCurrentX,gCurrentY
2880      var gDeltaX,gDeltaY
2881      var gMouseDown=false
2882      var gCurrentTranslate=document.documentElement.currentTranslate
2883
2884      function fnOnMouseDown(evt) {
2885      gCurrentX=gCurrentTranslate.x
2886      gCurrentY=gCurrentTranslate.y
2887      gDeltaX=evt.clientX
2888      gDeltaY=evt.clientY
2889      gMouseDown=true
2890      evt.target.ownerDocument.rootElement.setAttributeNS(null,"cursor","move")
2891      }
2892
2893
2894      function fnOnMouseUp(evt) {
2895      gMouseDown=false
2896      evt.target.ownerDocument.rootElement.setAttribute("cursor","default")
2897      }
2898
2899
2900      function fnOnMouseMove(evt) {
2901      var id
2902      if (gMouseDown) {
2903      gCurrentTranslate.x=gCurrentX+evt.clientX-gDeltaX
2904      gCurrentTranslate.y=gCurrentY+evt.clientY-gDeltaY
2905      }
2906      }
2907
2908
2909    </script>
2910  </xsl:template>
2911
2912</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.