TIP 507: Include simple SVG support with nanosvg

Login
Author:         René Zaumseil <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Created:        9-May-2018
Post-History:   
Keywords:       Tk
Tcl-Version:    8.7
Tk-Branch:      tip-507
Votes-For:      DKF, JN, FV, SL, AK
Votes-Against:  none
Votes-Present:  none

Abstract

Tk needs scalable images on high resolution mobile devices. This TIP proposes to let Tk be able to read an SVG image (plus information about orientation and pixel scale) and make it into a photo image. It is therefore a (lossy and single direction) conversion operation from an SVG format to a pixel format.

Rationale

Tk is running on desktop and mobile devices. However, the out-of-the-box photo image formats do not scale and are too tiny on high resolution mobile devices. The same goes for the image formats provided by the Img extension.

The response to this challenge in general (on the web, in applications, etc.) has been to adopt the SVG format, as that is scalable and does not typically depend on being rendered at a particular resolution. Moreover, there is already a Tk image extension to do the conversion, tksvg. The implementation is using the nanosvg library. It has no other external dependencies and is only 2 header files.

nanosvg was choosen because it:

Specification

The already existing tksvg extension will be adapted and included in Tk. A new photo image format will be created. The photo image format name is svg. The new format will support a small list of options. Note that scope still exists in the future for full integration of SVG as its own full image type (which would allow more options for rendering) instead of having the side-trip via the photo image's pixel buffer, but this is out of scope of this TIP. A description of the features and limitations of the current implementation is in section Supported SVG. It will be also described in the photo(n) man page.

The svg image format has the following format suboptions:

svg -dpi dpiValue -scale scaleValue -unit unitValue

dpiValue is used in conversion between given coordinates and screen resolution. The value must be greater then 0.0. The default value is 96.

scaleValue is used to scale the resulting image. The value must be greater then 0.0. The default value is 1.0.

unitValue is the unit of all coordinates in the svg data. Available units are px (default, coordinates in pixel), pt (1/72 inch), pc (12 pt), mm, cm and in.

The given format options are only used at creation time of the image and are not preserved in the image. This means that:

  1. $img data -format svg triggers the error "image string format "svg" is not supported"; Tk cannot convert a photo image into an SVG.

  2. In this:

    $img configure -format {svg -scale 2}
    $img configure -format {svg -dpi 96}
    

    the second call takes -scale as the default value (1).

There is no intention to provide a reverse mechanism for saving a photo image as an SVG image.

Supported SVG

The svg format supports a wide range of SVG features, however some features (e.g. 'text') are missing and silently ignored when reading the SVG data.

Elements

Attributes

Gradient Attributes

Poly Attributes

Line Attributes

Ellipse Attributes

Circle Attributes

Rectangle Attributes

Path Attributes

Style Attributes

Discussion

In http://code.activestate.com/lists/tcl-core/19994/ François Vogel mentioned his concerns.

Thread http://code.activestate.com/lists/tcl-core/19871/ is about compilers.

Thread http://code.activestate.com/lists/tcl-core/19985/ was the last discussion.

http://code.activestate.com/lists/tcl-core/20110/ and http://code.activestate.com/lists/tcl-core/20111/ talk about a better solution, not using the photo comand and instead making a p.e. svg command with full functionality (especially writing). This is imho out of scope of this tip. It should be addressed in a separate tip. If done so the new function can then be used to support the functionality in this tip.

There was some discussion on the further usage and maintenance of this image type. Here are the current state of the implementation in this area:

Implementation

A patch implementing these changes is available in the fossil repository in the tip-507 branch.

The new format is described in the photo(n) man page.

Example of use

# the image data
set data {<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<path fill="none" stroke="#000000" d="M0 0 h16 v16 h-16 z"/>
<path fill="none" stroke="#000000" d="M8 4 v 8 M4 8 h 8"/>
<circle fill="yellow" stroke="red" cx="10" cy="80" r="10" />
<ellipse fill="none" stroke="blue" stroke-width="3" cx="60" cy="60" rx="10" ry="20" />
<line x1="10" y1="90" x2="50" y2="99"/>
<rect fill="none" stroke="green"  x="20" y="20" width="60" height="50" rx="3" ry="3"/>
<polyline fill="red" stroke="purple" points="80,10 90,20 85,40"/>
<polygon fill ="yellow" points="80,80 70,85 90,90"/>
</svg>}
# create image
image create photo foo -data $data
# change size
foo configure -format {svg -scale 2}
# change dpi value
foo configure -format {svg -dpi 96}
# use other unit
foo configure -format {svg -unit mm}

Alternatives

Copyright

This document has been placed in the public domain.