1 <?xml version="1.0" ?> 2 3 <!-- 4 Copied from diagram-tools: 5 6 http://www.hokstad.com/making-graphviz-output-pretty-with-xsl.html 7 8 Copyright (c) 2012 Vidar Hokstad <vidar@hokstad.com> 9 Copyright (c) 2016, 2019, 2020 Paul Boddie <paul@boddie.org.uk> 10 11 Permission is hereby granted, free of charge, to any person obtaining a 12 copy of this software and associated documentation files (the "Software"), 13 to deal in the Software without restriction, including without limitation 14 the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 and/or sell copies of the Software, and to permit persons to whom the 16 Software is furnished to do so, subject to the following conditions: 17 18 The above copyright notice and this permission notice shall be included 19 in all copies or substantial portions of the Software. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 OTHER DEALINGS IN THE SOFTWARE. 28 --> 29 30 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 31 xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"> 32 <xsl:output method="xml" indent="yes" 33 doctype-public="-//W3C//DTD SVG 1.0//EN" 34 doctype-system="http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"/> 35 36 <xsl:variable name="text-style">font-size:10px; font-family:sans-serif;</xsl:variable> 37 38 <!-- Used to generate unique gradient fills for colors given by hex value 39 Search for generate-id to find where its used 40 --> 41 <xsl:key name="fills" match="*" use="@fill"/> 42 43 <xsl:template match="@*|node()"> 44 <xsl:copy> 45 <xsl:apply-templates select="@*|node()"/> 46 </xsl:copy> 47 </xsl:template> 48 49 <xsl:template match="svg:svg"> 50 <svg xmlns="http://www.w3.org/2000/svg"> 51 <!-- Order is important here, so the attributes below overrides the 52 originals, which are copied "wholesale" --> 53 <xsl:apply-templates select="@*" /> 54 55 <defs> 56 <linearGradient id="white" x1="0%" y1="0%" x2="0%" y2="0%"> 57 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 58 </linearGradient> 59 60 <linearGradient id="black" x1="0%" y1="0%" x2="0%" y2="0%"> 61 <stop offset="0%" style="stop-color:rgb(0,0,0);stop-opacity:1"/> 62 </linearGradient> 63 64 <linearGradient id="aquamarine" x1="0%" y1="0%" x2="100%" y2="100%"> 65 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 66 <stop offset="100%" style="stop-color:rgb(127,255,212);stop-opacity:1"/> 67 </linearGradient> 68 69 <linearGradient id="azure" x1="0%" y1="0%" x2="100%" y2="100%"> 70 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 71 <stop offset="100%" style="stop-color:rgb(240,255,255);stop-opacity:1"/> 72 </linearGradient> 73 74 <linearGradient id="blue" x1="0%" y1="0%" x2="100%" y2="100%"> 75 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 76 <stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1"/> 77 </linearGradient> 78 79 <linearGradient id="blueviolet" x1="0%" y1="0%" x2="100%" y2="100%"> 80 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 81 <stop offset="100%" style="stop-color:rgb(138,43,226);stop-opacity:1"/> 82 </linearGradient> 83 84 <linearGradient id="brown" x1="0%" y1="0%" x2="100%" y2="100%"> 85 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 86 <stop offset="100%" style="stop-color:rgb(165,42,42);stop-opacity:1"/> 87 </linearGradient> 88 89 <linearGradient id="cadetblue" x1="0%" y1="0%" x2="100%" y2="100%"> 90 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 91 <stop offset="100%" style="stop-color:rgb(95,158,160);stop-opacity:1"/> 92 </linearGradient> 93 94 <linearGradient id="chocolate" x1="0%" y1="0%" x2="100%" y2="100%"> 95 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 96 <stop offset="100%" style="stop-color:rgb(210,105,30);stop-opacity:1"/> 97 </linearGradient> 98 99 <linearGradient id="cornflowerblue" x1="0%" y1="0%" x2="100%" y2="100%"> 100 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 101 <stop offset="100%" style="stop-color:rgb(100,149,237);stop-opacity:1"/> 102 </linearGradient> 103 104 <linearGradient id="crimson" x1="0%" y1="0%" x2="100%" y2="100%"> 105 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 106 <stop offset="100%" style="stop-color:rgb(220,20,60);stop-opacity:1"/> 107 </linearGradient> 108 109 <linearGradient id="cyan" x1="0%" y1="0%" x2="100%" y2="100%"> 110 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 111 <stop offset="100%" style="stop-color:rgb(0,255,255);stop-opacity:1"/> 112 </linearGradient> 113 114 <linearGradient id="darkgreen" x1="0%" y1="0%" x2="100%" y2="100%"> 115 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 116 <stop offset="100%" style="stop-color:rgb(0,100,0);stop-opacity:1"/> 117 </linearGradient> 118 119 <linearGradient id="darkorange" x1="0%" y1="0%" x2="100%" y2="100%"> 120 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 121 <stop offset="100%" style="stop-color:rgb(255,140,0);stop-opacity:1"/> 122 </linearGradient> 123 124 <linearGradient id="gold" x1="0%" y1="0%" x2="100%" y2="100%"> 125 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 126 <stop offset="100%" style="stop-color:rgb(255,215,0);stop-opacity:1"/> 127 </linearGradient> 128 129 <linearGradient id="gray" x1="0%" y1="0%" x2="100%" y2="100%"> 130 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 131 <stop offset="100%" style="stop-color:rgb(192,192,192);stop-opacity:1"/> 132 </linearGradient> 133 134 <linearGradient id="greenyellow" x1="0%" y1="0%" x2="100%" y2="100%"> 135 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 136 <stop offset="100%" style="stop-color:rgb(173,255,47);stop-opacity:1"/> 137 </linearGradient> 138 139 <linearGradient id="green" x1="0%" y1="0%" x2="100%" y2="100%"> 140 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 141 <stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1"/> 142 </linearGradient> 143 144 <linearGradient id="grey" x1="0%" y1="0%" x2="100%" y2="100%"> 145 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 146 <stop offset="100%" style="stop-color:rgb(192,192,192);stop-opacity:1"/> 147 </linearGradient> 148 149 <linearGradient id="hotpink" x1="0%" y1="0%" x2="100%" y2="100%"> 150 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 151 <stop offset="100%" style="stop-color:rgb(255,105,180);stop-opacity:1"/> 152 </linearGradient> 153 154 <linearGradient id="indianred" x1="0%" y1="0%" x2="100%" y2="100%"> 155 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 156 <stop offset="100%" style="stop-color:rgb(205,92,92);stop-opacity:1"/> 157 </linearGradient> 158 159 <linearGradient id="indigo" x1="0%" y1="0%" x2="100%" y2="100%"> 160 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 161 <stop offset="100%" style="stop-color:rgb(75,0,130);stop-opacity:1"/> 162 </linearGradient> 163 164 <linearGradient id="lavender" x1="0%" y1="0%" x2="100%" y2="100%"> 165 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 166 <stop offset="100%" style="stop-color:rgb(230,230,250);stop-opacity:1"/> 167 </linearGradient> 168 169 <linearGradient id="lightblue" x1="0%" y1="0%" x2="100%" y2="100%"> 170 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 171 <stop offset="100%" style="stop-color:rgb(173,216,230);stop-opacity:1"/> 172 </linearGradient> 173 174 <linearGradient id="lightgray" x1="0%" y1="0%" x2="100%" y2="100%"> 175 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 176 <stop offset="100%" style="stop-color:rgb(211,211,211);stop-opacity:1"/> 177 </linearGradient> 178 179 <linearGradient id="lightgrey" x1="0%" y1="0%" x2="100%" y2="100%"> 180 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 181 <stop offset="100%" style="stop-color:rgb(211,211,211);stop-opacity:1"/> 182 </linearGradient> 183 184 <linearGradient id="magenta" x1="0%" y1="0%" x2="100%" y2="100%"> 185 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 186 <stop offset="100%" style="stop-color:rgb(255,0,255);stop-opacity:1"/> 187 </linearGradient> 188 189 <linearGradient id="maroon" x1="0%" y1="0%" x2="100%" y2="100%"> 190 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 191 <stop offset="100%" style="stop-color:rgb(176,48,96);stop-opacity:1"/> 192 </linearGradient> 193 194 <linearGradient id="mediumblue" x1="0%" y1="0%" x2="100%" y2="100%"> 195 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 196 <stop offset="100%" style="stop-color:rgb(0,0,205);stop-opacity:1"/> 197 </linearGradient> 198 199 <linearGradient id="mediumpurple" x1="0%" y1="0%" x2="100%" y2="100%"> 200 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 201 <stop offset="100%" style="stop-color:rgb(147,112,219);stop-opacity:1"/> 202 </linearGradient> 203 204 <linearGradient id="orange" x1="0%" y1="0%" x2="100%" y2="100%"> 205 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 206 <stop offset="100%" style="stop-color:rgb(255,165,0);stop-opacity:1"/> 207 </linearGradient> 208 209 <linearGradient id="pink" x1="0%" y1="0%" x2="100%" y2="100%"> 210 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 211 <stop offset="100%" style="stop-color:rgb(255,192,203);stop-opacity:1"/> 212 </linearGradient> 213 214 <linearGradient id="purple" x1="0%" y1="0%" x2="100%" y2="100%"> 215 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 216 <stop offset="100%" style="stop-color:rgb(160,32,240);stop-opacity:1"/> 217 </linearGradient> 218 219 <linearGradient id="red" x1="0%" y1="0%" x2="100%" y2="100%"> 220 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 221 <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/> 222 </linearGradient> 223 224 <linearGradient id="steelblue" x1="0%" y1="0%" x2="100%" y2="100%"> 225 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 226 <stop offset="100%" style="stop-color:rgb(70,130,180);stop-opacity:1"/> 227 </linearGradient> 228 229 <linearGradient id="violet" x1="0%" y1="0%" x2="100%" y2="100%"> 230 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 231 <stop offset="100%" style="stop-color:rgb(238,130,238);stop-opacity:1"/> 232 </linearGradient> 233 234 <linearGradient id="yellow" x1="0%" y1="0%" x2="100%" y2="100%"> 235 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 236 <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/> 237 </linearGradient> 238 239 <linearGradient id="none" x1="0%" y1="0%" x2="100%" y2="100%"> 240 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 241 <stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 242 </linearGradient> 243 244 <xsl:for-each select="*//*[generate-id() = generate-id(key('fills',@fill)[1])][substring(@fill,1,1)='#']"> 245 <linearGradient x1="0%" y1="0%" x2="100%" y2="100%"> 246 <xsl:attribute name="id">fill-<xsl:value-of select="substring(@fill,2,6)"/></xsl:attribute> 247 <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/> 248 <stop offset="100%"> 249 <xsl:attribute name="style">stop-color:<xsl:value-of select="@fill" />;stop-opacity:1</xsl:attribute> 250 </stop> 251 </linearGradient> 252 </xsl:for-each> 253 254 </defs> 255 256 257 <xsl:apply-templates /> 258 </svg> 259 </xsl:template> 260 261 <!-- Match the top most "g" --> 262 <xsl:template match="/svg:svg/svg:g"> 263 <g> 264 <xsl:apply-templates select="@*"/> 265 <!-- Graphviz uses a polygon as the background. Don't want a gradient there --> 266 <xsl:for-each select="svg:polygon"> 267 <xsl:copy><xsl:apply-templates select="@*" /></xsl:copy> 268 </xsl:for-each> 269 <xsl:apply-templates select="svg:title|svg:g" /> 270 </g> 271 </xsl:template> 272 273 274 <xsl:template match="svg:text"> 275 <text> 276 <xsl:apply-templates select="@*" /> 277 <xsl:if test="not(@font-family) and not(@font-size)"> 278 <xsl:attribute name="style"><xsl:value-of select="$text-style" /></xsl:attribute> 279 </xsl:if> 280 <xsl:apply-templates select="text()"/> 281 </text> 282 </xsl:template> 283 284 285 <xsl:template match="svg:g"> 286 <xsl:param name="class" select="@class"/> 287 288 <xsl:copy> 289 <xsl:apply-templates select="@*" /> 290 <xsl:choose> 291 <!-- Handle linked groups. --> 292 <xsl:when test="svg:a"> 293 <xsl:for-each select="svg:a"> 294 <xsl:copy> 295 <xsl:apply-templates select="@*" /> 296 <xsl:call-template name="group"> 297 <xsl:with-param name="class" select="$class"/> 298 </xsl:call-template> 299 </xsl:copy> 300 </xsl:for-each> 301 <!-- Handle labels. --> 302 <xsl:apply-templates select="svg:text" /> 303 </xsl:when> 304 <!-- Handle bare groups. --> 305 <xsl:otherwise> 306 <xsl:call-template name="group"/> 307 </xsl:otherwise> 308 </xsl:choose> 309 </xsl:copy> 310 </xsl:template> 311 312 313 <xsl:template name="group"> 314 <xsl:param name="class" select="@class"/> 315 316 <!-- Process any subgroups, apparent in Graphviz 2.38.0 output. --> 317 <xsl:apply-templates select="svg:g"> 318 <xsl:with-param name="class" select="$class"/> 319 </xsl:apply-templates> 320 321 <!-- Produce shadows for nodes. --> 322 <xsl:for-each select="svg:polygon|svg:ellipse"> 323 <xsl:call-template name="poly-shadow" /> 324 </xsl:for-each> 325 326 <xsl:choose> 327 <!-- Rewrite node outlines. --> 328 <xsl:when test="$class='node' and svg:path|svg:polyline"> 329 <xsl:call-template name="node-outline"> 330 <xsl:with-param name="current" select="*[1]"/> 331 <xsl:with-param name="style">shadow</xsl:with-param> 332 </xsl:call-template> 333 </xsl:when> 334 <xsl:otherwise> 335 <xsl:for-each select="svg:path"> 336 <xsl:call-template name="path-shadow-edge" /> 337 </xsl:for-each> 338 </xsl:otherwise> 339 </xsl:choose> 340 341 <xsl:for-each select="svg:polygon|svg:ellipse"> 342 <xsl:sort select="@ry" order="descending" /> 343 <xsl:call-template name="poly-main"> 344 <xsl:with-param name="class" select="$class"/> 345 </xsl:call-template> 346 </xsl:for-each> 347 348 <xsl:choose> 349 <!-- Rewrite node outlines. --> 350 <xsl:when test="$class='node' and svg:path|svg:polyline"> 351 <xsl:call-template name="node-outline"> 352 <xsl:with-param name="current" select="*[1]"/> 353 </xsl:call-template> 354 </xsl:when> 355 <xsl:otherwise> 356 <xsl:for-each select="svg:path"> 357 <path><xsl:apply-templates select="@*" /></path> 358 </xsl:for-each> 359 </xsl:otherwise> 360 </xsl:choose> 361 362 <!-- Handle labels. --> 363 <xsl:apply-templates select="svg:text" /> 364 </xsl:template> 365 366 <xsl:template name="node-outline"> 367 <xsl:param name="path-so-far"/> 368 <xsl:param name="current"/> 369 <xsl:param name="style"/> 370 371 <xsl:choose> 372 <!-- Visit each child element, collecting the path details. --> 373 <xsl:when test="$current"> 374 <xsl:choose> 375 <xsl:when test="local-name($current) = 'path'"> 376 <xsl:call-template name="filter-path"> 377 <xsl:with-param name="path-so-far" select="$path-so-far"/> 378 <xsl:with-param name="point" select="substring-before($current/@d, 'C')"/> 379 <xsl:with-param name="points" select="concat('C', substring-after($current/@d, 'C'))"/> 380 <xsl:with-param name="current" select="$current"/> 381 <xsl:with-param name="style" select="$style"/> 382 </xsl:call-template> 383 </xsl:when> 384 <xsl:when test="local-name($current) = 'polyline'"> 385 <xsl:call-template name="polyline-to-path"> 386 <xsl:with-param name="path-so-far" select="$path-so-far"/> 387 <xsl:with-param name="point" select="concat('M', substring-before($current/@points, ' '))"/> 388 <xsl:with-param name="points" select="substring-after($current/@points, ' ')"/> 389 <xsl:with-param name="current" select="$current"/> 390 <xsl:with-param name="style" select="$style"/> 391 </xsl:call-template> 392 </xsl:when> 393 <xsl:otherwise> 394 <xsl:call-template name="node-outline"> 395 <xsl:with-param name="path-so-far" select="$path-so-far"/> 396 <xsl:with-param name="current" select="$current/following-sibling::*[1]"/> 397 <xsl:with-param name="style" select="$style"/> 398 </xsl:call-template> 399 </xsl:otherwise> 400 </xsl:choose> 401 </xsl:when> 402 <!-- With no more elements to visit, generate the path. --> 403 <xsl:otherwise> 404 <xsl:choose> 405 <xsl:when test="$style = 'shadow'"> 406 <path style="fill: black; stroke: none; fill-opacity:0.15" transform="translate(3,3)" 407 d="{$path-so-far}"/> 408 </xsl:when> 409 <xsl:otherwise> 410 <!-- Provide the path attributes using dynamic colour discoveries. --> 411 <xsl:element name="path"> 412 <xsl:attribute name="d"><xsl:value-of select="$path-so-far"/></xsl:attribute> 413 <xsl:call-template name="make-style-attribute"> 414 <xsl:with-param name="fill" 415 select="normalize-space(substring-after(substring-before(ancestor::*[svg:polygon]/svg:polygon[1]/@style,';'),'fill:'))"/> 416 <xsl:with-param name="fill-explicit" 417 select="@fill"/> 418 <xsl:with-param name="stroke" 419 select="normalize-space(substring-after(substring-before(ancestor::*[svg:polygon]/svg:polygon[1]/@style,';'),'stroke:'))"/> 420 <xsl:with-param name="stroke-explicit">black</xsl:with-param> 421 <xsl:with-param name="none-is-transparent" select="true()"/> 422 </xsl:call-template> 423 </xsl:element> 424 </xsl:otherwise> 425 </xsl:choose> 426 </xsl:otherwise> 427 </xsl:choose> 428 </xsl:template> 429 430 <xsl:template name="filter-path"> 431 <xsl:param name="path-so-far"/> 432 <xsl:param name="point"/> 433 <xsl:param name="points"/> 434 <xsl:param name="current"/> 435 <xsl:param name="style"/> 436 437 <xsl:variable name="next" select="substring-before($points, ' ')"/> 438 <xsl:variable name="remaining" select="substring-after($points, ' ')"/> 439 440 <xsl:choose> 441 <!-- With path points remaining, include the current point if appropriate 442 and visit those remaining. --> 443 <xsl:when test="$remaining"> 444 <xsl:call-template name="filter-path"> 445 <xsl:with-param name="path-so-far" select="concat($path-so-far, ' ', $point)"/> 446 <xsl:with-param name="point" select="$next"/> 447 <xsl:with-param name="points" select="$remaining"/> 448 <xsl:with-param name="current" select="$current"/> 449 <xsl:with-param name="style" select="$style"/> 450 </xsl:call-template> 451 </xsl:when> 452 <!-- With up to one remaining after this point, include the current point, 453 if appropriate, and the one remaining. --> 454 <xsl:otherwise> 455 <xsl:call-template name="node-outline"> 456 <xsl:with-param name="path-so-far" select="concat($path-so-far, ' ', $point, ' ', $points)"/> 457 <xsl:with-param name="current" select="$current/following-sibling::*[1]"/> 458 <xsl:with-param name="style" select="$style"/> 459 <xsl:with-param name="last" select="$current"/> 460 </xsl:call-template> 461 </xsl:otherwise> 462 </xsl:choose> 463 </xsl:template> 464 465 <xsl:template name="polyline-to-path"> 466 <xsl:param name="path-so-far"/> 467 <xsl:param name="point"/> 468 <xsl:param name="points"/> 469 <xsl:param name="current"/> 470 <xsl:param name="style"/> 471 472 <xsl:variable name="next" select="substring-before($points, ' ')"/> 473 <xsl:variable name="remaining" select="substring-after($points, ' ')"/> 474 475 <xsl:choose> 476 <!-- With path points remaining, include the current point if appropriate 477 and visit those remaining. --> 478 <xsl:when test="$remaining"> 479 <xsl:call-template name="polyline-to-path"> 480 <xsl:with-param name="path-so-far" select="concat($path-so-far, ' ', $point)"/> 481 <xsl:with-param name="point" select="concat('L', $next)"/> 482 <xsl:with-param name="points" select="$remaining"/> 483 <xsl:with-param name="current" select="$current"/> 484 <xsl:with-param name="style" select="$style"/> 485 </xsl:call-template> 486 </xsl:when> 487 <!-- With up to one remaining after this point, include the current point, 488 if appropriate, and the one remaining. --> 489 <xsl:otherwise> 490 <xsl:call-template name="node-outline"> 491 <xsl:with-param name="path-so-far" select="concat($path-so-far, ' ', $point, ' L', $points)"/> 492 <xsl:with-param name="current" select="$current/following-sibling::*[1]"/> 493 <xsl:with-param name="style" select="$style"/> 494 <xsl:with-param name="last" select="$current"/> 495 </xsl:call-template> 496 </xsl:otherwise> 497 </xsl:choose> 498 </xsl:template> 499 500 <xsl:template name="poly-shadow"> 501 <xsl:element name="{name()}"> 502 <xsl:apply-templates select="@*"/> 503 <xsl:attribute name="style">fill: black; stroke: none; fill-opacity:0.3</xsl:attribute> 504 <xsl:attribute name="transform">translate(3,3)</xsl:attribute> 505 </xsl:element> 506 </xsl:template> 507 508 <xsl:template name="path-shadow-edge"> 509 <xsl:element name="{name()}"> 510 <xsl:apply-templates select="@*"/> 511 <xsl:attribute name="style">fill: none; stroke: black; stroke-opacity:0.3</xsl:attribute> 512 <xsl:attribute name="transform">translate(3,3)</xsl:attribute> 513 </xsl:element> 514 </xsl:template> 515 516 <xsl:template name="poly-main"> 517 <xsl:param name="class"/> 518 <xsl:element name="{name()}"> 519 <xsl:apply-templates select="@*" /> 520 <!-- Prevent edge polygons (such as arrowheads) from having gradients applied to them. --> 521 <xsl:if test="$class != 'edge'"> 522 <xsl:call-template name="make-style-attribute"> 523 <xsl:with-param name="fill" 524 select="normalize-space(substring-after(substring-before(@style,';'),'fill:'))"/> 525 <xsl:with-param name="fill-explicit" 526 select="@fill"/> 527 <xsl:with-param name="stroke" 528 select="normalize-space(substring-after(substring-after(@style,';'),'stroke:'))"/> 529 <xsl:with-param name="stroke-explicit" 530 select="@stroke"/> 531 </xsl:call-template> 532 </xsl:if> 533 </xsl:element> 534 </xsl:template> 535 536 <xsl:template name="path-main"> 537 <path> 538 <xsl:apply-templates select="@*" /> 539 <!-- This is somewhat broken - the gradient is set based on the position/size of the element it is used with; as a result it doesn't line up properly with the main polygon --> 540 <xsl:call-template name="make-style-attribute"> 541 <xsl:with-param name="fill" 542 select="normalize-space(substring-after(substring-before(ancestor::*[svg:polygon]/svg:polygon[1]/@style,';'),'fill:'))"/> 543 <xsl:with-param name="fill-explicit" 544 select="ancestor::*[svg:polygon]/svg:polygon[1]/@fill"/> 545 <xsl:with-param name="stroke" 546 select="normalize-space(substring-after(substring-before(ancestor::*[svg:polygon]/svg:polygon[1]/@style,';'),'stroke:'))"/> 547 <xsl:with-param name="stroke-explicit">black</xsl:with-param> 548 </xsl:call-template> 549 </path> 550 </xsl:template> 551 552 <xsl:template name="make-style-attribute"> 553 <xsl:param name="fill"/> 554 <xsl:param name="fill-explicit"/> 555 <xsl:param name="stroke"/> 556 <xsl:param name="stroke-explicit"/> 557 <xsl:param name="none-is-transparent" select="false()"/> 558 559 <xsl:attribute name="style"> 560 <xsl:choose> 561 <xsl:when test="$fill and (not($none-is-transparent) or $fill != 'none')"> 562 <xsl:call-template name="make-style-fill"> 563 <xsl:with-param name="fill" select="$fill"/> 564 </xsl:call-template> 565 </xsl:when> 566 <xsl:when test="$fill-explicit and (not($none-is-transparent) or $fill-explicit != 'none')"> 567 <xsl:choose> 568 <xsl:when test="starts-with($fill-explicit, '#')"> 569 <xsl:call-template name="make-style-fill"> 570 <xsl:with-param name="fill" select="$fill-explicit"/> 571 </xsl:call-template> 572 </xsl:when> 573 <xsl:otherwise>fill: url(#<xsl:value-of select="$fill-explicit"/>);</xsl:otherwise> 574 </xsl:choose> 575 </xsl:when> 576 <xsl:otherwise>fill: none;</xsl:otherwise> 577 </xsl:choose> 578 <xsl:choose> 579 <xsl:when test="$stroke">stroke: <xsl:value-of select="$stroke"/>;</xsl:when> 580 <xsl:when test="$stroke-explicit">stroke: <xsl:value-of select="$stroke-explicit"/>;</xsl:when> 581 <xsl:otherwise>stroke: black;</xsl:otherwise> 582 </xsl:choose> 583 </xsl:attribute> 584 </xsl:template> 585 586 <xsl:template name="make-style-fill"> 587 <xsl:param name="fill"/> 588 <xsl:choose> 589 <xsl:when test="substring($fill,1,1) = '#'">fill: url(#fill-<xsl:value-of select="substring($fill,2,6)"/>);</xsl:when> 590 <xsl:otherwise>fill: url(#<xsl:value-of select="$fill"/>);</xsl:otherwise> 591 </xsl:choose> 592 </xsl:template> 593 594 </xsl:stylesheet>