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

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

Update with Dodi's corrected Alpha 4 version

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