Dealt with thickness of rounded rectangle properly, within named template
[rdsigngen:mainline.git] / roadsigngen.xsl
1 <?xml version="1.0"?>
2 <xsl:stylesheet version="2.0"\r
3                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
4                 xmlns:xs="http://www.w3.org/2001/XMLSchema"\r
5                 xmlns:rdsign="http://www.example.com/rdsign"
6                 xmlns="http://www.w3.org/2000/svg"\r
7                 exclude-result-prefixes="xs rdsign">\r
8 <xsl:output method="xml" media-type="image/svg+xml"\r
9             indent="yes" encoding="ISO-8859-1" />
10 <xsl:strip-space elements="*" />
11 \r
12 <xsl:variable name="widths" as="document-node()" select="doc('widths.xml')" />\r
13 <xsl:variable name="rdsign" as="document-node()" select="/" />\r
14 <xsl:key name="IDs" match="Character" use="@id" />\r
15 \r
16 <!-- top level match: add SVG boilerplate here -->
17 <!-- it will need to have width & height calculations -->\r
18 <xsl:template match="/">\r
19         <svg
20     version="1.0"
21     width="100"
22     height="100">
23     \r
24         <xsl:apply-templates />\r
25         </svg>\r
26 </xsl:template>
27
28 \r
29 \r
30 <xsl:template match="sign">
31     <!-- calculate sign width and height -->
32     <xsl:variable name="signwidth" select="max(\r
33                         for $legend in legend\r
34                         return sum(rdsign:length(rdsign:characters($legend))))" />
35         <xsl:variable name="signheight" select="sum(legend/@padding-top) + 8 * count(legend)" /> <!-- number of lines, plus padding -->
36                         
37     <!-- draw rounded rect -->
38     <xsl:call-template name="roundrect">
39         <xsl:with-param name="width" select="$signwidth + 8" />
40         <xsl:with-param name="height" select="$signheight + 7" />
41         <xsl:with-param name="x" select="0" />
42         <xsl:with-param name="y" select="0" />
43         <xsl:with-param name="strokewidth" select="1.5" />
44         <xsl:with-param name="ry" select="1.5" />
45     </xsl:call-template>
46         \r
47         <numchars>\r
48                 <!-- this calculates max number of characters (not very useful!) -->\r
49                 <xsl:value-of select="max(\r
50                         for $legend in legend\r
51                         return string-length($legend))" />\r
52         </numchars>\r
53     <!-- add text -->
54     <g transform="translate(4 4)"> <!-- to bring within safe margin of the rounded rect (ch 7 fig 2.4)-->
55     
56     <!-- debug rectangle
57     <rect style="fill:none;fill-opacity:1;stroke:red;stroke-width:0.5;stroke-opacity:1" width="{$signwidth}" height="{$signheight}" x="0" y="0" />
58     -->
59     
60     <text style="font-size:7.44186046512px;font-style:normal;font-weight:normal;fill:black;font-family:Transport Heavy" x="0" y="8">\r
61         <xsl:apply-templates select="legend">
62             <xsl:with-param name="signwidth" select="$signwidth" />
63         </xsl:apply-templates>
64         </text>
65         </g>
66         \r
67 </xsl:template>\r
68 \r
69 <xsl:template match="legend">
70     <xsl:param name="signwidth" as="xs:double" required="yes" />
71     <!-- assume that x=0, y=0 is top left of panel -->
72     <xsl:variable name="legendwidth" select="sum(rdsign:length(rdsign:characters(.)))" />
73     
74     <xsl:variable name="x" as="xs:double">
75     <!-- unless centre-aligned, x=0 -->
76         <xsl:choose>
77             <xsl:when test="@align = 'center'">
78                 <xsl:value-of select="($signwidth - $legendwidth) *0.5" />
79             </xsl:when>
80             <xsl:otherwise>0</xsl:otherwise>
81         </xsl:choose>
82     </xsl:variable>
83     
84     <xsl:variable name="dy" as="xs:double">
85     <!-- difference in y: 8 sw unless extra padding specified -->
86         <xsl:choose>
87             <xsl:when test="position() = 1">
88                 0
89             </xsl:when>
90             <xsl:otherwise>
91                 <xsl:value-of select="(if (@padding-top) then @padding-top else 0) + 8" />
92             </xsl:otherwise>
93         </xsl:choose>
94     </xsl:variable>
95     
96     <tspan x="{$x}" dy="{$dy}">
97     <xsl:apply-templates />
98     </tspan>
99                 \r
100 </xsl:template>\r
101
102 <!-- Named templates -->
103 <xsl:template name="roundrect">
104     <xsl:param name="width" as="xs:double" required="yes" />
105     <xsl:param name="height" as="xs:double" required="yes" />
106     <xsl:param name="x" as="xs:double" required="yes" />
107     <xsl:param name="y" as="xs:double" required="yes" />
108     <xsl:param name="strokewidth" as="xs:double" required="yes" />
109     <xsl:param name="ry" as="xs:double" />
110     <rect style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:{$strokewidth};stroke-opacity:1"
111     width="{$width - $strokewidth}" height="{$height - $strokewidth}"
112         x="{$x + 0.5*$strokewidth}" y="{$y + 0.5*$strokewidth}"
113         ry="{$ry}" />
114 </xsl:template>
115 \r
116 <!-- Functions -->\r
117 <!-- TODO can these be coerced into named templates, to allow compatibility with XSLT1.0? 
118 http://www.dpawson.co.uk/xsl/sect2/N8090.html#d10831e823 , Tenison p245-->\r
119 <xsl:function name="rdsign:characters" as="xs:string*">\r
120   <!-- breaks down a string into individual characters -->\r
121   <xsl:param name="string" as="xs:string" />\r
122   <xsl:if test="$string">\r
123     <xsl:sequence select="substring($string, 1, 1)" />\r
124     <xsl:variable name="remainder" select="substring($string, 2)" as="xs:string" />\r
125     <xsl:if test="$remainder">\r
126       <xsl:sequence select="rdsign:characters($remainder)" />\r
127     </xsl:if>\r
128   </xsl:if>\r
129 </xsl:function>\r
130 \r
131 <xsl:function name="rdsign:length" as="xs:decimal+">\r
132   <!-- calculates total width of a set of characters using alphabet tile widths -->\r
133   <xsl:param name="chars" as="xs:string+" />\r
134         <xsl:for-each select="$chars" >\r
135                 <xsl:value-of select="key('IDs',., $widths)/Width" />\r
136         </xsl:for-each>\r
137 </xsl:function>\r
138 \r
139 </xsl:stylesheet>\r