Project

Profile

Help

Bug #1545 » svg-t5-browser-v2.xsl

Manfred Staudinger, 2012-06-19 07:55

 
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="2.0"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
xmlns:prop="http://saxonica.com/ns/html-property"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xlink="http://www.w3.org/1999/xlink"
extension-element-prefixes="ixsl"
xmlns:plan="http://www.plan.com"
xmlns:js="http://saxonica.com/ns/globalJS"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="svg" select="ixsl:page()/html:html/html:body/svg:svg" as="element(svg:svg)"/>
<xsl:variable name="g" select="$svg/svg:g/svg:g/svg:g" as="element(svg:g)+"/>
<xsl:variable name="file-name-base" select="substring-before(ixsl:page()/html:html/*/html:script[@data-source]/@data-source, '.')" as="xs:string"/>
<xsl:variable name="tab" select="doc('../svg-t5-tab.xml')/*" as="element(plan:tab)"/>
<xsl:variable name="feature_TextFlow" select="ixsl:eval('document.implementation.hasFeature(&quot;http://www.w3.org/Graphics/SVG/feature/1.2/#TextFlow&quot;, &quot;1.2&quot;)')" as="xs:boolean"/>
<xsl:key name="class" match="plan:class" use="."/><!-- svg-t5-tab.xml -->
<xsl:key name="text" match="plan:text" use="@id"/><!-- svg-t5-011.xml -->

<xsl:template match="/">
<xsl:for-each select="ixsl:page()/html:html/html:head">
<xsl:result-document href="?select=." method="ixsl:append-content">
<script language="JavaScript">
var jumpScroll = function(x, y) {
window.scroll(x,y);
}
</script>
</xsl:result-document>
</xsl:for-each>
<xsl:result-document href="#title" method="ixsl:replace-content">
<xsl:value-of select="$svg/svg:title"/>
</xsl:result-document>
<xsl:for-each select="ixsl:page()/html:html/html:body/html:div[1]">
<xsl:call-template name="switch"/>
</xsl:for-each>

<xsl:apply-templates select="$g, $g/*" mode="init-attr"/>

<xsl:variable name="innerWidthHeight" select="ixsl:get(ixsl:window(), 'innerWidth'), ixsl:get(ixsl:window(), 'innerHeight') - 4 (: -4 to avoid scroll bar, error? :)" as="xs:double+"/>
<xsl:variable name="innerWidthHeight" select="for $i in $innerWidthHeight return xs:integer($i)" as="xs:integer+"/>
<xsl:message select="'$innerWidthHeight', $innerWidthHeight"/>
<xsl:variable name="t" select="ixsl:call($svg/svg:g, 'getBBox')
(: boundingbox of an svg element (userspace coordinate system) :)" as="item()"/>
<xsl:variable name="BBox" select="ixsl:get($t, 'x'), ixsl:get($t, 'y'), ixsl:get($t, 'width'), ixsl:get($t, 'height')" as="xs:double+"/>
<xsl:message select="'$BBox of $svg/svg:g', $t, $BBox"/>
<xsl:variable name="t" select="ixsl:call(ixsl:call($svg/svg:g, 'getScreenCTM'), 'inverse')" as="item()"/>
<xsl:variable name="ScreenCTM" select="ixsl:get($t, 'a'), ixsl:get($t, 'b'), ixsl:get($t, 'c'), ixsl:get($t, 'd'), ixsl:get($t, 'e'), ixsl:get($t, 'f')" as="xs:double+"/>
<xsl:message select="'$ScreenCTM inverse of $svg/svg:g', $t, $ScreenCTM"/>
<xsl:variable name="scale" select="min(for $i in 1 to 2 return $innerWidthHeight[$i] div $BBox[$i+2]) * ixsl:get($t, 'a')" as="xs:double"/>
<xsl:message select="'$scale', $scale"/>
<!-- $BBox[3] div $ScreenCTM[1] = $ScreenBBox[3], $BBox[4] div $ScreenCTM[1] = $ScreenBBox[4] -->
<xsl:apply-templates select="$svg" mode="init-scale">
<xsl:with-param name="svgWH" select="$innerWidthHeight" as="xs:double+" tunnel="yes"/>
<xsl:with-param name="viewBox" select="(0, 0, $BBox[3] div ixsl:get($t, 'a'), $BBox[4] div ixsl:get($t, 'a'))" as="xs:double+" tunnel="yes"/>
<xsl:with-param name="scale" select="$scale (: used only for @transform and @viewBox :)" as="xs:double" tunnel="yes"/>
<xsl:with-param name="scale_next" select="1" as="xs:double" tunnel="yes"/>
</xsl:apply-templates>

<xsl:call-template name="init_form"/>
<ixsl:schedule-action wait="1">
<xsl:call-template name="init_test"/>
</ixsl:schedule-action>
</xsl:template>

<xsl:template name="init_test">
<xsl:message select="'main: init_test'"/>
<xsl:call-template name="init_last"/>
</xsl:template>
<xsl:template name="init_last">
<xsl:variable name="t" select="ixsl:call(ixsl:call($svg/svg:g, 'getScreenCTM'), 'inverse')" as="item()"/>
<xsl:variable name="ScreenCTM" select="ixsl:get($t, 'a'), ixsl:get($t, 'b'), ixsl:get($t, 'c'), ixsl:get($t, 'd'), ixsl:get($t, 'e'), ixsl:get($t, 'f')" as="xs:double+"/>
<xsl:message select="'$ScreenCTM inverse of $svg/svg:g', $t, $ScreenCTM"/>
<xsl:message select="'Schriftgröße 12px', round(12 * $ScreenCTM[1]), '@data-CTM_translate', concat($ScreenCTM[5], ' ', $ScreenCTM[6])"/>
<xsl:for-each select="$g[@id='Texte']/svg:g[@id='Texte_4']">
<ixsl:set-attribute name="font-size" select="round(12 * ixsl:get($t, 'a')) (: Schriftgröße 12px :)"/>
</xsl:for-each>
<xsl:for-each select="$svg">
<ixsl:set-attribute name="data-CTM_translate" select="concat(ixsl:get($t, 'e'), ' ', ixsl:get($t, 'f'))"/>
</xsl:for-each>
<xsl:message select="concat('Load ', $file-name-base, '.xml and build an index of its id attributes'),
key('text', '???', doc(concat($file-name-base, '.xml')))"/>
</xsl:template>
<xsl:template name="init_form">
<xsl:result-document href="#group-titles">
<form xmlns="http://www.w3.org/1999/xhtml">
<span>
<xsl:value-of select="'Vergrößerung:'"/>
<br/>
<input type="radio" name="scale" value="1" checked=""/>
<xsl:value-of select="'1x '"/>
<input type="radio" name="scale" value="2"/>
<xsl:value-of select="'2x '"/>
<input type="radio" name="scale" value="4"/>
<xsl:value-of select="'4x '"/>
<input type="radio" name="scale" value="6"/>
<xsl:value-of select="'6x '"/>
<input type="radio" name="scale" value="8"/>
<xsl:value-of select="'8x '"/>
<input type="radio" name="scale" value="10"/>
<xsl:value-of select="'10x '"/>
</span>
<table>
<tbody>
<xsl:for-each select="$g/@id">
<xsl:sort data-type="number" select="if (key('class', ., $tab/plan:init)/@sort)
then key('class', ., $tab/plan:init)/@sort else '22'"/>
<tr>
<xsl:variable name="title" select="." as="xs:string"/>
<td><xsl:value-of select="translate($title, '_', ' ')"/></td>
<td>
<input type="checkbox" name="genre" value="{$title}">
<xsl:if test="not(key('class', $title, $tab/plan:init)[@display='none'])">
<xsl:attribute name="checked" select="'checked'"/>
</xsl:if>
</input>
</td>
<xsl:for-each select="1 to 4">
<td>
<xsl:variable name="title" select="concat($title, '_', current())" as="xs:string"/>
<xsl:if test="$g/svg:g[@id=$title] or $g/svg:use[@xlink:href=concat('#', $title)]">
<input type="checkbox" name="genre" value="{$title}">
<xsl:if test="not(key('class', $title, $tab/plan:init)[@display='none'])">
<xsl:attribute name="checked" select="'checked'"/>
</xsl:if>
</input>
</xsl:if>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</form>
</xsl:result-document>
</xsl:template>
<xsl:template match="svg:g[key('class', @id, $tab/plan:init)]" mode="init-attr">
<xsl:apply-templates select="key('class', @id, $tab/plan:init)/@*" mode="init-attr">
<xsl:with-param name="curr-elem" select="." as="element()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="svg:use[key('class', substring(@xlink:href, 2), $tab/plan:init)]" mode="init-attr">
<xsl:apply-templates select="key('class', substring(@xlink:href, 2), $tab/plan:init)/@*" mode="init-attr">
<xsl:with-param name="curr-elem" select="." as="element()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="svg:use[@clip-path]" mode="init-attr"/>
<xsl:template match="*" mode="init-attr"/>
<xsl:template match="@*" mode="init-attr">
<xsl:param name="curr-elem" as="element()"/>
<xsl:variable name="att-name" select="name(.)" as="xs:string"/>
<xsl:variable name="att-value" select="." as="xs:string"/>
<xsl:for-each select="$curr-elem">
<ixsl:set-attribute name="{$att-name}" select="$att-value"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="@sort" mode="init-attr"/>
<xsl:template match="@gsort" mode="init-attr"/>

<xsl:template name="switch">
<xsl:message select="'switch: context', name(.), */@src, if (not(contains(*/@src, 'hide'))) then 'hide' else 'show'"/>
<xsl:result-document href="?select=." method="ixsl:replace-content">
<img src="../html-{if (not(contains(*/@src, 'hide'))) then 'hide' else 'show'}.png" alt="Tanzmaus"/>
</xsl:result-document>
</xsl:template>
<xsl:template name="scroll">
<xsl:param name="scroll_xy" as="xs:integer+"/>
<xsl:message select="'scroll: $scroll_xy', $scroll_xy"/>
<xsl:sequence select="js:jumpScroll($scroll_xy[1], $scroll_xy[2])"/>
</xsl:template>
<xsl:template match="html:input[@type='radio']" mode="ixsl:onclick">
<xsl:variable name="scale_next" select="xs:double(@prop:value)" as="xs:double+"/>
<xsl:message select="'onclick radio', '@WH', xs:double($svg/@width), xs:double($svg/@height),
'@data-scale_curr, $scale_next', $svg/@data-scale_curr, $scale_next"/>
<xsl:apply-templates select="$svg" mode="scale">
<xsl:with-param name="svgWH" select="for $i in ($svg/@width, $svg/@height)
return round($i * $scale_next div xs:double($svg/@data-scale_curr))" as="xs:double+" tunnel="yes"/>
<xsl:with-param name="scale_next" select="$scale_next" as="xs:double" tunnel="yes"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="svg:svg" mode="init-scale scale">
<xsl:param name="svgWH" as="xs:double+" tunnel="yes"/>
<xsl:param name="viewBox" select="0" as="xs:double+" tunnel="yes"/>
<xsl:param name="scale" select="0" as="xs:double" tunnel="yes"/>
<xsl:param name="scale_next" as="xs:double" tunnel="yes"/>
<xsl:message select="'scale:', @id, 'oldWH', @width, @height, 'newWH', $svgWH"/>
<ixsl:set-attribute name="width" select="$svgWH[1]"/>
<ixsl:set-attribute name="height" select="$svgWH[2]"/>
<ixsl:set-attribute name="data-scale_curr" select="string($scale_next)"/>
<xsl:apply-templates select="*" mode="#current"/>
<xsl:choose>
<xsl:when test="not($scale=0) (: mode=init-scale :)">
<xsl:variable name="viewBox" select="string-join((for $i in $viewBox return string(round($i * $scale * 1000) div 1000)), ' ')"/>
<xsl:message select="'scale:', @id, 'viewBox', $viewBox"/>
<ixsl:set-attribute name="preserveAspectRatio" select="'xMidYMid meet'"/>
<ixsl:set-attribute name="viewBox" select="$viewBox"/>
<ixsl:set-attribute name="data-last_click_xy" select="string-join((for $i in $svgWH return string(round($i div 2))), ' ')"/>
</xsl:when>
<xsl:when test="not($scale_next = 1) (: mode=scale :)">
<xsl:variable name="innerWidthHeight" select="ixsl:get(ixsl:window(), 'innerWidth'), ixsl:get(ixsl:window(), 'innerHeight') - 4 (: -4 to avoid scroll bar, error? :)" as="xs:double+"/>
<xsl:message select="'scroll: $innerWidthHeight', $innerWidthHeight, '@data-last_click_xy', @data-last_click_xy"/>
<xsl:variable name="scroll_xy" select="for $i in tokenize(@data-last_click_xy, ' ') return xs:double($i) * $scale_next" as="xs:double+"/>
<ixsl:schedule-action wait="1">
<xsl:call-template name="scroll">
<xsl:with-param name="scroll_xy" select="for $i in 1 to 2 return
max((xs:integer(round($scroll_xy[$i] - $innerWidthHeight[$i] div 2)), 0))" as="xs:integer+"/>
</xsl:call-template>
</ixsl:schedule-action>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template match="svg:svg/svg:g[@transform]" mode="init-scale">
<xsl:param name="scale" as="xs:double" tunnel="yes"/>
<xsl:variable name="t" select="ixsl:call($svg/svg:g, 'getBBox')
(: boundingbox of an svg element (userspace coordinate system) :)" as="item()"/>
<xsl:variable name="BBox" select="ixsl:get($t, 'x'), ixsl:get($t, 'y'), ixsl:get($t, 'width'), ixsl:get($t, 'height')" as="xs:double+"/>
<xsl:message select="'scale: $BBox of $svg/svg:g', $t, $BBox"/>
<ixsl:set-attribute name="transform" select="concat(@transform, ' scale(', $scale, ') translate(', ixsl:get($t, 'x') * -1, ',', ixsl:get($t, 'y') * -1, ')')"/>
</xsl:template>
<xsl:template match="svg:g[@id='Texte_4']" mode="scale">
<xsl:param name="scale_next" as="xs:double" tunnel="yes"/>
<ixsl:set-attribute name="font-size" select="round(xs:double(@font-size) * xs:double($svg/@data-scale_curr) div $scale_next)"/>
<xsl:apply-templates select="*" mode="scale"/>
</xsl:template>
<xsl:template match="svg:textArea" mode="scale">
<xsl:param name="scale_next" as="xs:double" tunnel="yes"/>
<xsl:message select="'scale: @data-scale_curr, $scale_next', $svg/@data-scale_curr, $scale_next, 'textArea: oldWH', @width, @height"/>
<ixsl:set-attribute name="width" select="round(xs:double(@width) * xs:double($svg/@data-scale_curr) div $scale_next)"/>
<ixsl:set-attribute name="height" select="round(xs:double(@height) * xs:double($svg/@data-scale_curr) div $scale_next)"/>
</xsl:template>
<xsl:template match="*" mode="init-scale scale">
<xsl:apply-templates select="*" mode="#current"/>
</xsl:template>

<xsl:template match="html:input[@type='checkbox']" mode="ixsl:onclick">
<xsl:variable name="class" select="@prop:value" as="xs:string"/>
<xsl:apply-templates select="$svg//svg:g/svg:g[@id=$class] | $svg//svg:g/svg:use[substring(@xlink:href, 2)=$class]" mode="display">
<xsl:with-param name="checked" select="@prop:checked" as="xs:boolean"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="svg:g" mode="display">
<xsl:message select="'display', name(.), @id"/>
<xsl:apply-templates select="svg:g" mode="#current"/>
</xsl:template>
<xsl:template match="svg:g/*" mode="display">
<xsl:param name="checked" as="xs:boolean"/>
<xsl:choose>
<xsl:when test="$checked">
<ixsl:remove-attribute name="display"/>
</xsl:when>
<xsl:otherwise>
<ixsl:set-attribute name="display" select="'none'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="svg:use[@clip-path]" mode="display"/>

<xsl:template match="html:div[1]" mode="ixsl:onclick">
<xsl:call-template name="switch"/>
<xsl:for-each select="following-sibling::*[1]">
<xsl:choose>
<xsl:when test="not(@style)">
<ixsl:set-attribute name="style" select="'display:none;'"/>
</xsl:when>
<xsl:otherwise>
<ixsl:remove-attribute name="style"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>

<xsl:template match="svg:path" mode="ixsl:onclick">
<xsl:variable name="curr-elem" select="(.|..)[svg:title][1]" as="element()"/>
<xsl:variable name="top-class" select="$curr-elem/../../@id" as="xs:string"/>
<xsl:variable name="att-names" select="for $i in $tab/plan:click/plan:class[.=$top-class]/@* return name($i)" as="xs:string*"/>
<xsl:choose>
<!-- when not(A): set-attribute(s), add A -->
<xsl:when test="not(id('Texte_4')/*[@id = concat('_', $curr-elem/svg:title)])">
<xsl:variable name="att-values" select="for $i in $tab/plan:click/plan:class[.=$top-class]/@* return $i" as="xs:string*"/>
<xsl:for-each select="$att-names">
<xsl:variable name="i" select="position()"/>
<xsl:for-each select="$curr-elem">
<ixsl:set-attribute name="{$att-names[$i]}" select="$att-values[$i]"/>
</xsl:for-each>
</xsl:for-each>
<xsl:variable name="evt" select="ixsl:event()"/>
<xsl:variable name="evt_pageXY" select="ixsl:get($evt, 'pageX'), ixsl:get($evt, 'pageY')" as="xs:double+"/>
<xsl:for-each select="$svg">
<ixsl:set-attribute name="data-last_click_xy" select="string-join((for $i in $evt_pageXY
return string(round($i div $svg/@data-scale_curr))), ' ')"/>
</xsl:for-each>
<xsl:variable name="t" select="ixsl:call(ixsl:call($curr-elem, 'getScreenCTM'), 'inverse')" as="item()"/>
<xsl:message select="'onclick path: $ScreenCTM inverse', $t, ixsl:get($t, 'a'), ixsl:get($t, 'b'), ixsl:get($t, 'c'), ixsl:get($t, 'd'), ixsl:get($t, 'e'), ixsl:get($t, 'f')"/>
<xsl:variable name="CTM_translate" select="for $i in tokenize($svg/@data-CTM_translate, ' ') return xs:double($i)" as="xs:double+"/>
<xsl:variable name="xy" select="for $i in 1 to 2 return round(($evt_pageXY[$i] * ixsl:get($t, 'a')) + $CTM_translate[$i])" as="xs:double+"/>
<xsl:message select="'onclick path: $evt_pageXY', $evt_pageXY,
'ScreenCTM inverse[a]', ixsl:get($t, 'a'), '@data-CTM_translate', $svg/@data-CTM_translate, '->', $xy"/>
<xsl:variable name="msg" select="key('text', $curr-elem/svg:title, doc(concat($file-name-base, '.xml')))" as="element()"/>
<xsl:variable name="msg-txt" select="tokenize(concat($msg, ' [', $msg/@id, ']'), '\t')" as="xs:string+"/>
<xsl:result-document href="#Texte_4" method="ixsl:append-content">
<xsl:choose>
<xsl:when test="$feature_TextFlow"><!-- svg:textArea supported: Opera 11.62 -->
<xsl:variable name="width" select="round(160 * ixsl:get($t, 'a'))"/>
<xsl:variable name="height" select="round(100 * ixsl:get($t, 'a'))"/>
<xsl:message select="'onclick path, textArea: width, height', $width, $height"/>
<textArea id="_{$curr-elem/svg:title}" x="{$xy[1]}" y="{$xy[2]}" width="{$width}" height="{$height}" xmlns="http://www.w3.org/2000/svg">
<title><xsl:value-of select="$curr-elem/svg:title"/></title>
<xsl:for-each select="$msg-txt">
<xsl:sequence select="."/>
<tbreak/>
</xsl:for-each>
</textArea>
</xsl:when>
<xsl:otherwise><!-- workaround: svg:textArea not supported -->
<text id="_{$curr-elem/svg:title}" x="{$xy[1]}" y="{$xy[2]}" xmlns="http://www.w3.org/2000/svg">
<title><xsl:value-of select="$curr-elem/svg:title" /></title>
<xsl:for-each select="$msg-txt">
<tspan x="{$xy[1]}" dy="1.1em"><xsl:sequence select="."/></tspan>
</xsl:for-each>
</text>
</xsl:otherwise>
</xsl:choose>
</xsl:result-document>
</xsl:when>
<!-- otherwise: remove-attribute(s), del A -->
<xsl:otherwise>
<xsl:for-each select="$att-names">
<xsl:variable name="i" select="position()"/>
<xsl:for-each select="$curr-elem">
<ixsl:remove-attribute name="{$att-names[$i]}"/>
</xsl:for-each>
</xsl:for-each>
<xsl:result-document href="#Texte_4" method="ixsl:replace-content">
<xsl:for-each select="id('Texte_4')/*[not(@id = concat('_', $curr-elem/svg:title))]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:result-document>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:transform>
(7-7/12)