SVGHMI: attempt to optimize for webkit, because of really slow style recompute in svg:use : "unlink clones" (as in inkscape) but stop deep-copy when meeting a widget, and create a new clone instead.
--- a/svghmi/gen_index_xhtml.xslt Fri Feb 21 16:18:53 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt Fri Feb 21 16:22:44 2020 +0100
@@ -102,8 +102,8 @@
</xsl:template>
<xsl:template mode="inline_svg" match="svg:svg/@width"/>
<xsl:template mode="inline_svg" match="svg:svg/@height"/>
- <xsl:template mode="inline_svg" match="svg:svg">
- <xsl:copy>
+ <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:svg">
+ <svg>
<xsl:attribute name="preserveAspectRatio">
<xsl:text>none</xsl:text>
</xsl:attribute>
@@ -114,7 +114,7 @@
<xsl:text>100vw</xsl:text>
</xsl:attribute>
<xsl:apply-templates mode="inline_svg" select="@* | node()"/>
- </xsl:copy>
+ </svg>
</xsl:template>
<xsl:template mode="inline_svg" match="svg:svg[@viewBox!=concat('0 0 ', @width, ' ', @height)]">
<xsl:message terminate="yes">
@@ -126,6 +126,40 @@
<xsl:text>All units must be set to "px" in Inkscape's document properties</xsl:text>
</xsl:message>
</xsl:template>
+ <xsl:template xmlns="http://www.w3.org/2000/svg" mode="inline_svg" match="svg:use">
+ <g>
+ <xsl:attribute name="style">
+ <xsl:value-of select="@style"/>
+ </xsl:attribute>
+ <xsl:attribute name="transform">
+ <xsl:value-of select="@transform"/>
+ </xsl:attribute>
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ <xsl:variable name="targetid" select="substring-after(@xlink:href,'#')"/>
+ <xsl:apply-templates mode="unlink_clone" select="//svg:*[@id = $targetid]"/>
+ </g>
+ </xsl:template>
+ <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="@*">
+ <xsl:copy/>
+ </xsl:template>
+ <xsl:template xmlns="http://www.w3.org/2000/svg" mode="unlink_clone" match="svg:*">
+ <xsl:choose>
+ <xsl:when test="@id = $hmi_elements/@id">
+ <use>
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="concat('#',@id)"/>
+ </xsl:attribute>
+ </use>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy>
+ <xsl:apply-templates mode="unlink_clone" select="@* | node()"/>
+ </xsl:copy>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
<xsl:template match="/">
<xsl:comment>
<xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
@@ -139,7 +173,7 @@
<xsl:comment>
<xsl:apply-templates mode="testtree" select="$indexed_hmitree"/>
</xsl:comment>
- <html xmlns="http://www.w3.org/1999/xhtml">
+ <html xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/1999/xhtml">
<head/>
<body style="margin:0;overflow:hidden;">
<xsl:apply-templates mode="inline_svg" select="svg:svg"/>
@@ -333,9 +367,9 @@
<xsl:value-of select="$desc/arg[1]/@value"/>
<xsl:text>": {
</xsl:text>
- <xsl:text> id: "</xsl:text>
+ <xsl:text> widget: hmi_widgets["</xsl:text>
<xsl:value-of select="@id"/>
- <xsl:text>",
+ <xsl:text>"],
</xsl:text>
<xsl:text> bbox: [</xsl:text>
<xsl:value-of select="$p/@x"/>
@@ -824,17 +858,65 @@
</xsl:text>
<xsl:text> let new_desc = page_desc[page_name];
</xsl:text>
- <xsl:text> /* TODO hide / show widgets */
+ <xsl:text>
+</xsl:text>
+ <xsl:text> if(new_desc == undefined){
+</xsl:text>
+ <xsl:text> return;
+</xsl:text>
+ <xsl:text> }
</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text> /* remove subsribers of previous page if any */
</xsl:text>
- <xsl:text> if(old_desc) for(let widget of old_desc.widgets){
+ <xsl:text> if(old_desc){
+</xsl:text>
+ <xsl:text> for(let widget of old_desc.widgets){
+</xsl:text>
+ <xsl:text> for(let index of widget.indexes){
+</xsl:text>
+ <xsl:text> subscribers[index].delete(widget);
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> old_desc.widget.element.style.display = "none";
+</xsl:text>
+ <xsl:text> } else {
+</xsl:text>
+ <xsl:text> /* initial page switch : set everybody hidden */
+</xsl:text>
+ <xsl:text> for(let name in page_desc){
+</xsl:text>
+ <xsl:text> if(name != new_desc){
+</xsl:text>
+ <xsl:text> page_desc[name].widget.element.style.display = "none";
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text> }
+</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text> /* add new subsribers if any */
+</xsl:text>
+ <xsl:text> for(let widget of new_desc.widgets){
</xsl:text>
<xsl:text> for(let index of widget.indexes){
</xsl:text>
- <xsl:text> subscribers[index].delete(widget);
+ <xsl:text> subscribers[index].add(widget);
+</xsl:text>
+ <xsl:text> /* dispatch current cache in newly opened page widgets */
+</xsl:text>
+ <xsl:text> let cached_val = cache[index];
+</xsl:text>
+ <xsl:text> if(cached_val != undefined)
+</xsl:text>
+ <xsl:text> dispatch_value_to_widget(widget, index, cached_val, cached_val);
</xsl:text>
<xsl:text> }
</xsl:text>
@@ -842,31 +924,11 @@
</xsl:text>
<xsl:text>
</xsl:text>
- <xsl:text> if(new_desc) {
-</xsl:text>
- <xsl:text> /* add new subsribers if any */
-</xsl:text>
- <xsl:text> for(let widget of new_desc.widgets){
-</xsl:text>
- <xsl:text> for(let index of widget.indexes){
-</xsl:text>
- <xsl:text> subscribers[index].add(widget);
-</xsl:text>
- <xsl:text> let cached_val = cache[index];
-</xsl:text>
- <xsl:text> if(cached_val != undefined)
-</xsl:text>
- <xsl:text> dispatch_value_to_widget(widget, index, cached_val, cached_val);
-</xsl:text>
- <xsl:text> }
-</xsl:text>
- <xsl:text> }
-</xsl:text>
- <xsl:text> svg_root.setAttribute('viewBox',new_desc.bbox.join(" "));
-</xsl:text>
- <xsl:text> // TODO dispatch current cache in newly opened page
-</xsl:text>
- <xsl:text> }
+ <xsl:text> new_desc.widget.element.style.display = "inline";
+</xsl:text>
+ <xsl:text>
+</xsl:text>
+ <xsl:text> svg_root.setAttribute('viewBox',new_desc.bbox.join(" "));
</xsl:text>
<xsl:text> current_page = page_name;
</xsl:text>
--- a/svghmi/gen_index_xhtml.ysl2 Fri Feb 21 16:18:53 2020 +0100
+++ b/svghmi/gen_index_xhtml.ysl2 Fri Feb 21 16:22:44 2020 +0100
@@ -133,6 +133,43 @@
error > All units must be set to "px" in Inkscape's document properties
}
+ /* clone unlinkink until widget for better perf with webkit */
+ svgtmpl "svg:use", mode="inline_svg"
+ {
+ g{
+ attrib "style" > «@style»
+ attrib "transform" > «@transform»
+ /* keep same id and label in case it is a widget */
+ //attrib "inkscape:label","@inkscape:label";
+ attrib "id" > «@id»
+ const "targetid","substring-after(@xlink:href,'#')";
+ apply "//svg:*[@id = $targetid]", mode="unlink_clone";
+ }
+ }
+ svgtmpl "@*", mode="unlink_clone" xsl:copy;
+ svgtmpl "svg:*", mode="unlink_clone" {
+ choose {
+ when "@id = $hmi_elements/@id" {
+ use{
+ attrib "xlink:href" > «concat('#',@id)»
+ }
+ }
+ otherwise {
+ xsl:copy apply "@* | node()", mode="unlink_clone";
+ }
+ }
+ }
+
+ // template "svg:use/@style", mode="inline_svg"{
+ // attrib "style" > all:initial;
+ // //«.»
+ // }
+
+ // template "svg:*[concat('#',@id) = //svg:use/@xlink:href]/@style", mode="inline_svg"{
+ // attrib "style" > all:unset;
+ // //«.»
+ // }
+
/*const "mark" > =HMI=\n*/
/* copy root node and add geometry as comment for a test */