See also SVG widgets Part 1 & SVG widgets Part 2
)
By clicking on the button, an interactive demo is displayed in a new browser tab using CloudTk.
This article is written by Vladimir Orlov.
So, the moment has finally arrived when it's become possible to easily use graphic images stored in SVG files when developing GUIs in tcl/tk:

SVG files are text files with the .svg extension, containing XML code describing images as geometric primitives: lines, curves, shapes, text, etc.
Using SVG graphics in tcl/tk became possible after Mats Bengtsson developed the tkpath package. At the same time, Mats Bengtsson, as part of the Coccinella project, also began implementing a package for working with SVG files (with SVG-xml code). The package was called svg2can. As its name suggests, it was intended for placing vector graphics described by XML code on the canvas of the tkp::canvas widget. Unfortunately, this work was interrupted at the very beginning; Mats Bengtsson passed away on November 29, 2008. Shortly before his death, Mats Bengtsson wrote:
SVG Graphics
Thu, 17/07/2008 - 13:31 — matben
Just released is my tkpath package version 0.3.0 which for the first time brings a new canvas widget to Tcl/Tk which conforms to a more "modern" 2D drawing model found in SVG.
My motiviation for producing close to 43 thousand lines of C code for just this widget is because it is necessary for adding SVG graphics to the whiteboard in Coccinella. It doesn't claim to be a full featured SVG viewer. In fact, there is no support for translating svg tkpath yet, but since I have carefully designed the widget with SVG in mind, it shouldn't be too difficult to write such script code. SVG is really big and I don't claim every part is supported. For instance, clipping is yet unsupported. Remember, it is still version 0.3.0.
For the curious you can visit the SourceForge page where some screenshots can be found and the complete sources can be checked out.
For me, the key phrase in this message was "there's no support for translating SVG to tkpath yet." And I took it upon myself to fill this gap. This was made possible, first and foremost, by the thoughtful implementation of the SVG canvas widget tkp::canvas. I'll reiterate Mats's words, which I completely agree with:
In fact, there is no support for translating svg tkpath yet, but since I have carefully designed the widget with SVG in mind, it shouldn't be too difficult to write such script code.
And today, this code for converting XML vector graphics code into primitives from the tkpah package was written. It's the svg2can package, version 2.0.
I'd like to point out right away that the examples discussed, as well as the svgwidgets package, the svg2can package, and the tclexecomp64 interpreters for Linux and Windows platforms with the necessary packages, can be found on GitHub. All of them have been updated since the previous article.
At the beginning of the article, I mentioned the phrase "when developing GUIs in tcl/tk, it became possible to easily use images/icons stored in SVG files." Judge for yourself. After launching the TkCon cloud console from the demo example (the button at the beginning of the article), just execute a few commands to display an image from the SVG file ./images/DocCat.svg on the canvas:
#Loading the svg2can package
package require svg2can
#Create window
toplevel .svg -bg yellow
#Create SVG canvas
tkp::canvas .svg.tkp -bg cyan
# Displaying SVG file on canvas
set gidsvg [svg2can::SVGFileToCanvas .svg.tkp ./images/DogCat.svg]
pack .svg.tkp -in .svg -fill both -expand 1 -padx 3m -pady 3m

The svg2can::SVGFileToCanvas command from the svg2can package has the following format:
svg2can::SVGFileToCanvas <svg canvas> <path to the svg file>
If you'd like, you can also view the contents of the file itself here:
The file's contents are now stored in an xml variable, and you can view its contents in various ways.
In addition to the svg2can::SVGFileToCanvas command, there's also the svg2can::SVGXmlToCanvas command, which is identical to the SVG file display command, except that instead of a file name, it specifies a string containing the image's xml code (e.g., the contents of the xml variable - $xml):
svg2can::SVGXmlToCanvas <svg-canvas> <string with XML code>
If successful, both commands return the group ID (hereinafter simply referred to as "group") in which all image elements are grouped. The created SVG image is uniquely identified by the ID of the SVG canvas on which it is located and the ID (number) of its group. We'll return to this shortly. As a reminder, to get all image elements, simply execute the command:
<svg canvas with image> children <group ID>
The svg2can::SVGXmlToCanvas command is easy to verify:
Obviously, the image on the canvas needs to be positioned in a specific location and have specific dimensions. To place the image at the appropriate coordinates, use the group clone command:
svg2can::copy <canvas with image> <new canvas> <group ID to copy> [<parameters>]
This command clones the specified image (<canvas with image> and <group>) to the specified canvas (<new canvas>) and returns the group ID on the new canvas. Naturally, cloning can also be performed within a single canvas. After cloning, the original can be destroyed (if no longer needed):
<canvas with image> delete <group ID>
The clone's coordinates and dimensions on the canvas are specified by a list of parameters:
-x <X-coordinate>
-y <Y-coordinate>
-width <image width>
-height <image height>
Image characteristics can be obtained using the bbox command:
<canvas with image> bbox <group ID>
For example, let's clone our image of the dog and kitten, reduce its size by half, and position it to the right of the reference image:

There's another command for working with SVG files:
svg2can::SVGFileToCmds <svg canvas> <path to svg file>
This command can be used for debugging. It doesn't place anything on the canvas, but returns a list of generated commands from the tkpath package, which are used to display an image from an SVG file on the SVG canvas. Everything was fine until I tried using an SVG file of the US national flag as an icon on the interface language switch button:
The flag turned out to be single-starred (left screenshot) instead of multi-starred (right screenshot):

No messages were received. Analysis of the SVG file revealed that the <use> element is elegantly used in the XML markup to render the Stars and Stripes flag, while the svg2can::SVGXmlToCanvas command simply ignores it. This ignoring is clearly visible in the screenshot.
The same situation applies to displaying this flag on the native tcl/tk canvas, meaning the image command also doesn't process the "use" element found in SVG files:

The svg2can package uses commands from the tkpath package for rendering SVG files (support for the tko package has now been added). I tried to write some TCL code to interpret XML code with "use" elements into tkpath package commands, but I quickly realized there was no straightforward way to solve this problem. Here's what one person wrote:
Parsing svg is trivial; it's just a xml. However interpreting it is another matter.
But! I came across the wonderful resvg project.
In addition to the library, the resvg project also includes two utilities: resvg and usvg. Resvg, which converts an SVG file to a png image, is not of interest to us in this context. However, usvg turned out to be the solution to the problem of the "use" element (and other issues) in SVG files. The usvg utility converts the input SVG file into a strongly typed tree structure, where all elements, attributes, links, and other SVG features are already configured and presented in the simplest possible form, omitting the "use" element. This eliminates most of the issues associated with parsing SVG files and allows you to focus solely on the rendering stage. Anyone can see how the usvg utility works by applying it to an SVG file of the stars and stripes:
usvg <source svg file> <output svg file>
Save the flag's XML code in the file FlagUSuse.svg, run it through the usvg utility, and save the result in the file FlagUSusvg.svg:
$usvg FlagUSuse.svg FlagUSusvg.svg
If you look at the resulting file, you won't find a single "use" element. Now let's create an image object using the new SVG file:
set img4 [image create photo -file FlagUSusvg.svg -format {svg -scaletowidth 190}]
And now we'll insert it into the .svg.lab widget:
.svg.lab configure –image $img4
The US flag has taken on its familiar Stars and Stripes appearance (see the right screenshot above). A similar result was obtained when rendering the processed SVG file using commands from the svg2can package (the command svg2can::SVGFileToCanvas <svg-canvas> <svg-file> or svg2can::SVGXmlToCanvas <svg-canvas> <svg-file>).
After that, the natural desire arose for a tcl package for parsing SVG files based on the resvg library. And then it turned out I wasn't the only one concerned about this problem. I stumbled upon the brand new tresvg project.
This is a very nice tcl wrapper around the resvg library. I would recommend it as a tutorial. It has everything – support for various operating systems, integration with various programming languages (Rust, C, Tcl/tk), and the use of various technologies. The only thing that was confusing was the use of a ton of additional packages. That's why I decided to create a simple package – a counterpart to the usvg utility. Thus, the tclusvg package was born, based on the resvg library, incorporating the resvg_tree_to_xml function from the tresvg project. Currently, the tclusvg package implements a single command of the same name:
The tclusvg command takes a string as its parameters, which can contain the name of an SVG file (default or the -file option) or an XML structure describing the SVG image (the -data option). If the -size option is specified, the command returns the image size as a list of <width> and <height>:
If the -size option is not specified, the SVG image's XML code is returned in the simplest possible form, which can now be rendered using either the standard tcl/tk image command or commands from the svg2can package. The fundamental difference between these two rendering methods is that when using the svg2can package, we continue to work with the image as an SVG image, and we can easily change both its individual characteristics and its geometry without losing quality. Incidentally, this remark also applies to the tresvg package.
The svgwidgets project on GitHub contains both a Linux64 version of the tclexecomp graphical interpreter (folder tclexexcomp902), built from the tcl/tk-9.0.2 source code, and a tcl/tk-8.6-based interpreter for Linux64 and Win64 platforms (folder tclexecomp200), including the tclusvg, svg2can, and svgwidgets packages.
Two folders, SVGviewFile and SVGviewFolders, have been added to the TkSVGwidgets project folder. These folders contain two tcl utilities for viewing SVG files using the tclusvg package:

By running the SVGviewFolders utility, you can view the SVG files in the folder:

This screenshot (the "Choose directory" window on the right) also shows an alternative file manager (package require tkfe_svg), which can also be found on GitHub in the TkSVGWidgets project. The tkfe_svg package will be the subject of a separate article.
The last screenshot shows many icons in various SVG widgets.
These SVG widgets currently include ibutton and cbutton class widgets of the rect and square types (-type rect | square). Icons can also be SVG images or image objects created with the image create photo command.
An icon can be specified either when creating an object (the –image or -isvg parameter) or added to an existing object:
If the icon is an image, it is defined by the name assigned to it when it was created. An SVG icon is defined by a list of two elements. The first element specifies the SVG canvas where the icon image is located, and the second is the ID of the group containing the image.
Let's look at how this works with an example. First, let's remove the SVG canvas .svg.tkp from the screen:
destroy .svg.tkp
After that, we'll create all three types of SVG widgets that can contain icons.
For one widget, we'll select an image icon. You can view the full list of available image icons using the command
%image names
…
::tk::icons::question
…
From the resulting list, select the "::tk::icons::question" icon.
We'll be using an SVG icon for another widget. We discussed how to create one from an SVG file above. Here we'll show you how the tkpath package works.
As an example, let's look at the folderbrown function. Its input parameter is an SVG canvas on which a chocolate-colored folder icon will be drawn, and the return value is the ID of the group containing the SVG image:
Before calling the folderbrown function, let's create a temporary SVG canvas (which we won't display on-screen) to create an SVG image that will serve as an icon in one of our widgets. After placing the icon in the widget, you can delete it and the SVG canvas it was created on:

Icons in SVG widgets of class cbutton and type rect can be placed to the right, left, above or below the text, or centered. This placement is specified with the -conpound right | left | top | bottom | none. The size of the icon itself and its offset from the widget's borders are specified with the -ipad option, which is a list of four values:
-ipad {<x-offset> <icon width> <y-offset> <icon height>}
The same -ipad option for the SVG widget of the same cbutton class, but the square type, is interpreted slightly differently:
-ipad {<offset left> <offset right> <offset top> <offset bottom>}
If the -ipad option contains only one value, this means all offsets have the same value. If the option contains two values, the first value specifies the margins to the left and right of the image, and the second value specifies the margins to the top and bottom of the image.
The -pad option for the ibutton class SVG widget is treated similarly:
-pad {<offset left> <offset right> <offset top> <offset bottom>}
The SVGviewFile and SVGviewFolders examples discussed above, as well as the SVGbutton example, demonstrate the use of SVG icons very clearly:

Part four will cover information widgets, including callouts, and the file manager.