Edouard@2878: // inline_svg.ysl2 Edouard@2878: // Edouard@2878: // Produce Inline SVG element of resulting XHTML page. Edouard@2779: edouard@2937: // Since stylesheet output namespace is xhtml, templates that output svg have to be explicitely declared as such edouard@2937: in xsl decl svgtmpl(match, xmlns="http://www.w3.org/2000/svg") alias template; edouard@2937: in xsl decl svgfunc(name, xmlns="http://www.w3.org/2000/svg") alias template; edouard@2937: edouard@2937: Edouard@2878: // Identity template : Edouard@2878: // - copy every attributes Edouard@2878: // - copy every sub-elements Edouard@3030: Edouard@3030: svgtmpl "@*", mode="inline_svg" xsl:copy; Edouard@3030: Edouard@3030: template "node()", mode="inline_svg" { Edouard@2878: // use real xsl:copy instead copy-of alias from yslt.yml2 Edouard@2878: if "not(@id = $discardable_elements/@id)" Edouard@2878: xsl:copy apply "@* | node()", mode="inline_svg"; Edouard@2878: } Edouard@2792: Edouard@2878: // replaces inkscape's height and width hints. forces fit Edouard@2878: template "svg:svg/@width", mode="inline_svg"; Edouard@2878: template "svg:svg/@height", mode="inline_svg"; Edouard@2878: svgtmpl "svg:svg", mode="inline_svg" svg { Edouard@2878: attrib "preserveAspectRatio" > none Edouard@2878: attrib "height" > 100vh Edouard@2878: attrib "width" > 100vw Edouard@2878: apply "@* | node()", mode="inline_svg"; Edouard@2878: } Edouard@2878: // ensure that coordinate in CSV file generated by inkscape are in default reference frame Edouard@2878: template "svg:svg[@viewBox!=concat('0 0 ', @width, ' ', @height)]", mode="inline_svg" { Edouard@2878: error > ViewBox settings other than X=0, Y=0 and Scale=1 are not supported Edouard@2878: } Edouard@2878: // ensure that coordinate in CSV file generated by inkscape match svg default unit Edouard@2878: template "sodipodi:namedview[@units!='px' or @inkscape:document-units!='px']", mode="inline_svg" { Edouard@2878: error > All units must be set to "px" in Inkscape's document properties Edouard@2878: } Edouard@2792: edouard@3108: // remove i18n markers, so that defs_by_labels can find text elements edouard@3108: svgtmpl "svg:text/@inkscape:label[starts-with(., '_')]", mode="inline_svg" { edouard@3108: attrib "{name()}" > «substring(., 2)» edouard@3108: } edouard@3108: edouard@2941: ////// Clone unlinking edouard@2941: // Edouard@2878: // svg:use (inkscape's clones) inside a widgets are Edouard@2878: // replaced by real elements they refer in order to : Edouard@2878: // - allow finding "needle" element in "meter" widget, Edouard@2878: // even if "needle" is in a group refered by a svg use. Edouard@2878: // - if "needle" is visible through a svg:use for Edouard@2878: // each instance of the widget, then needle would show Edouard@2878: // the same position in all instances Edouard@2878: // Edouard@2878: // For now, clone unlinkink applies to descendants of all widget except HMI:Page Edouard@2878: // TODO: narrow application of clone unlinking to active elements, Edouard@2878: // while keeping static decoration cloned edouard@3027: const "targets_not_to_unlink", "$hmi_lists/descendant-or-self::svg:*"; Edouard@3384: const "to_unlink", "$hmi_widgets/descendant-or-self::svg:use"; Edouard@3030: Edouard@3030: def "func:is_unlinkable" { Edouard@3030: param "targetid"; Edouard@3030: param "eltid"; Edouard@3030: result "$eltid = $to_unlink/@id and not($targetid = $targets_not_to_unlink/@id)"; Edouard@3030: } Edouard@3030: Edouard@3030: svgtmpl "svg:use", mode="inline_svg"{ edouard@2995: const "targetid","substring-after(@xlink:href,'#')"; Edouard@2878: choose { Edouard@3030: when "func:is_unlinkable($targetid, @id)" { edouard@3027: call "unlink_clone" { edouard@3027: with "targetid", "$targetid"; Edouard@3030: } Edouard@3030: } Edouard@3030: otherwise xsl:copy apply "@*", mode="inline_svg"; Edouard@2878: } Edouard@2878: } Edouard@2877: Edouard@2878: // to unlink a clone, an group containing a copy of target element is created Edouard@2878: // that way, style and transforms can be preserved Edouard@2878: const "_excluded_use_attrs" { Edouard@2878: name > href Edouard@2878: name > width Edouard@2878: name > height Edouard@2878: name > x Edouard@2878: name > y edouard@3027: name > id Edouard@2878: } Edouard@2878: const "excluded_use_attrs","exsl:node-set($_excluded_use_attrs)"; Edouard@2794: Edouard@2968: const "_merge_use_attrs" { Edouard@2968: name > transform Edouard@2968: name > style Edouard@2968: } Edouard@2968: const "merge_use_attrs","exsl:node-set($_merge_use_attrs)"; Edouard@2968: Edouard@2878: svgfunc "unlink_clone"{ edouard@2995: param "targetid"; Edouard@3030: param "seed","''"; Edouard@2968: const "target", "//svg:*[@id = $targetid]"; Edouard@3030: const "seeded_id" choose { Edouard@3030: when "string-length($seed) > 0" > «$seed»_«@id» Edouard@3030: otherwise value "@id"; Edouard@3030: } Edouard@2878: g{ edouard@3027: attrib "id" value "$seeded_id"; Edouard@3030: attrib "original" value "@id"; Edouard@3030: Edouard@2968: choose { Edouard@2968: when "$target[self::svg:g]" { Edouard@2968: foreach "@*[not(local-name() = $excluded_use_attrs/name | $merge_use_attrs)]" Edouard@2968: attrib "{name()}" > «.» Edouard@2853: Edouard@2968: if "@style | $target/@style" Edouard@2968: attrib "style" { Edouard@2968: > «@style» Edouard@2968: if "@style and $target/@style" > ; Edouard@2968: > «$target/@style» Edouard@2968: } Edouard@2968: Edouard@2968: if "@transform | $target/@transform" Edouard@2968: attrib "transform" { Edouard@2968: > «@transform» Edouard@2968: if "@transform and $target/@transform" > Edouard@2968: > «$target/@transform» Edouard@2968: } Edouard@2968: Edouard@2968: apply "$target/*", mode="unlink_clone"{ Edouard@3030: with "seed","$seeded_id"; Edouard@2968: } Edouard@2968: } Edouard@2968: otherwise { Edouard@2968: // include non excluded attributes Edouard@2968: foreach "@*[not(local-name() = $excluded_use_attrs/name)]" Edouard@2968: attrib "{name()}" > «.» Edouard@2968: Edouard@2968: apply "$target", mode="unlink_clone"{ Edouard@3030: with "seed","$seeded_id"; Edouard@2968: } Edouard@2968: } Edouard@2854: } Edouard@2854: } Edouard@2878: } Edouard@2854: Edouard@2878: // clone unlinking is really similar to deep-copy Edouard@2878: // all nodes are sytematically copied Edouard@2878: svgtmpl "@id", mode="unlink_clone" { Edouard@2878: param "seed"; Edouard@2878: attrib "id" > «$seed»_«.» Edouard@3030: attrib "original" > «.» Edouard@2878: } Edouard@2854: Edouard@2878: svgtmpl "@*", mode="unlink_clone" xsl:copy; Edouard@2854: edouard@3027: svgtmpl "svg:use", mode="unlink_clone" { edouard@3027: param "seed"; Edouard@3030: const "targetid","substring-after(@xlink:href,'#')"; Edouard@3030: choose { Edouard@3030: when "func:is_unlinkable($targetid, @id)" { Edouard@3030: call "unlink_clone" { Edouard@3030: with "targetid", "$targetid"; Edouard@3030: with "seed","$seed"; Edouard@3030: } Edouard@3030: } Edouard@3030: otherwise xsl:copy apply "@*", mode="unlink_clone" { Edouard@3030: with "seed","$seed"; Edouard@3030: } Edouard@3030: } edouard@3027: } edouard@3027: Edouard@2878: // copying widgets would have unwanted effect Edouard@2878: // instead widget is refered through a svg:use. Edouard@2878: svgtmpl "svg:*", mode="unlink_clone" { Edouard@2878: param "seed"; Edouard@2878: choose { Edouard@2878: // node recursive copy ends when finding a widget Edouard@2878: when "@id = $hmi_elements/@id" { Edouard@2878: // place a clone instead of copying Edouard@2878: use{ Edouard@2878: attrib "xlink:href" > «concat('#',@id)» Edouard@2878: } Edouard@2878: } Edouard@2878: otherwise { Edouard@2878: xsl:copy apply "@* | node()", mode="unlink_clone" { Edouard@2878: with "seed","$seed"; Edouard@2854: } Edouard@2854: } Edouard@2854: } Edouard@2878: } Edouard@2854: Edouard@2878: const "result_svg" apply "/", mode="inline_svg"; Edouard@2878: const "result_svg_ns", "exsl:node-set($result_svg)"; Edouard@2854: edouard@2941: emit "preamble:inline-svg" { edouard@2941: | let id = document.getElementById.bind(document); edouard@2941: | var svg_root = id("«$svg/@id»"); edouard@2941: } edouard@2941: edouard@2941: emit "debug:clone-unlinking" { edouard@2941: | edouard@2904: | Unlinked : Edouard@2878: foreach "$to_unlink"{ Edouard@2878: | «@id» Edouard@2808: } edouard@2995: | Not to unlink : edouard@2995: foreach "$targets_not_to_unlink"{ edouard@2995: | «@id» edouard@2995: } Edouard@2753: }