Inkscape.org
Using Inkscape with Other Programs Annotating objects in the SVG XML to define template fields
  1. #1
    Stuart Longland Stuart Longland @sjlongland
    *

    Hi all,

    I'm working on a project where I would like to define a template image with fields that can be filled in by an external application.  My use case is using slow-scan television images, but the applications for a feature like this are obviously far more widely applicable than this.

    In my specific situation, probably the most advanced thing I'd be doing would be when I receive a transmission from someone and want to reply, usually in the reply transmission I want to embed details like:

    • the call-sign of the operator I'm replying to
    • the operator's name (if I know it)
    • a "signal report" (normally a 3 digit number comprising of "readability" [1-5 rating; 1=poor - 5=good], "signal strength" [1-9] and picture quality [1-5]).
    • a copy of the image I received
    • optionally a comment

    To make things more interesting, it's common practice to put an image of one's own choosing as the "background".  If you watch https://www.worldsstv.com/ long enough, you'll see plenty of examples of this.

    It occurred to me that SVG is very capable of doing this, and Inkscape is one of the best-in-class tools for manipulating SVGs.  I just need something that I can embed some semantic data into the SVG XML file to tell the external program that "this SVG object is a template field".  It's also one of the best tools to rasterise the SVG to a bitmap for transmission.

    There are a few ways I can think of to do this:

    • Placeholder strings
    • Dummy CSS classes
    • Nested XML namespace tags
    • XSLT templates

    Placeholder strings was my first attempt, I entered the field values using Python format string format, e.g. %(comment)s and using Python's % operator with a pre-filled dict to perform the substitutions.  This works okay aside from the sequence %; tripping Python up.  For bitmap image fields it is problematic because Inkscape expects a real file name, not a placeholder… if I replace file:///path/to/image with %(receivedimage)s, Inkscape (understandably) gets very confused.  It's also very cumbersome.

    I looked through the interface and found I could define CSS classes, and assign those to objects.  This worked quite well, I could then use a generic XML parser to read in the resulting SVG file, use a XPath expression to find all the objects that have a CSS class assigned to them, replace the text (or image URI), then spit out a SVG image with the fields filled in.  Perfect!  Assigning the CSS classes is a bit awkward but I documented the process in a recent blog post.

    https://vk4msl.com/2024/07/15/hacking-sstv/

    I wonder if a second <style> tag in the XML with a known name intended for declaring classes used for semantic purposes might be possible.  That said, a big limitation of this approach is that you can't really define any properties of the field (e.g. data type, purpose, etc).

    The gold standard would be one of the XML native methods.  XSLTs are complicated, but can do a hell of a lot.  The W3C actually produced a paper on this topic back in 2002.

    https://www.w3.org/People/maxf/papers/2002-07-SVGOpen/svgopen.html

    A simpler option might be to define a URN defined in the SVG opening, and using that to specify custom attributes and tags along-side the native SVG ones:

    <svg
       width="320"
       height="256"
       viewBox="0 0 84.666665 67.733333"
       version="1.1"
       id="svg1"
       inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
       sodipodi:docname="test.svg"
       xml:space="preserve"
       xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
       xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       xmlns="http://www.w3.org/2000/svg"
       xmlns:svg="http://www.w3.org/2000/svg"
       xmlns:inkscapetemplate="urn:inkscape:template">
    <inkscapetemplate:field name="utcdate" type="string" description="Current date in UTC" />
    
    <!-- … snip … -->
    <text
           xml:space="preserve"
           style="font-weight:bold;font-size:4.23333px;line-height:125%;font-family:'Terminus (TTF)';-inkscape-font-specification:'Terminus (TTF), Bold';writing-mode:lr-tb;fill:#ffffff;stroke:#010101;stroke-width:1.05833;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke markers fill"
           x="0.86024231"
           y="7.8177671"
           id="utcdate"><tspan
             sodipodi:role="line"
             id="tspan1"
             style="stroke-width:1.05833"
             inkscapetemplate:value-fieldname="utcdate"
             x="0.86024231"
             y="7.8177671">YYYY-mm-dd</tspan></text>
    </svg>
    

    Have others tried doing something like this, or have any idea how feasible it'd be to implement such a feature in Inkscape to be able to do things like the above?

  2. #2
    inklinea inklinea @inklinea⛰️

    I think the trick is to use something that is 100% transparent and does not cause any conflicts.

    SVG has https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/data-*

    For that reason.

    It doesn't require any workarounds / custom namespaces.

    The attribute can be retrieved easily in python (lxml etree) and also in javascript (DOM) if you are loading svgs into browser.

    In the extension system Inkscape uses Inkex to load the svg into a modified etree with lots of helper functions.

    As for styles, you have have as many <style> blocks as you like. 

    I always put any custom styles in a 2nd block with an id of my own.

    Inkscape doesn't always like it if you start changing the first style block programatically

     

  3. #3
    Stuart Longland Stuart Longland @sjlongland

    Ahh okay, so in the plug-in system I can directly manipulate the XML and add custom "data" attributes… right.  That might be a viable way forward, certainly in the short-medium term.

    I think CSS might support something similar, now I think about it.  When I look at the style tag on a text field, there's a -inkscape-font-specification that most definitely is not part of the W3C CSS specs, so maybe a second style block with -inkscape-template-* properties to define data types, defaults and descriptions, might be an option.

    Many thanks for pointing this out… I think this helps define a workable path forward.

Inkscape Inkscape.org Inkscape Forum Using Inkscape with Other Programs Annotating objects in the SVG XML to define template fields