Zig NEWS

Cover image for A challenger to the throne of vector graphics. SVG is dead,  long live TinyVG!
Felix "xq" Queißner
Felix "xq" Queißner

Posted on • Updated on

A challenger to the throne of vector graphics. SVG is dead, long live TinyVG!

SVG must go

No, seriously, hear me out!

I needed vector graphics for a Zig project and I figured that everyone inluding myself is using SVG. So I wanted to use SVG. What it learned in the process that implementing a new SVG library is hard.

First of all, SVG is built on top of several other technologies:

  • XML
  • CSS
  • ECMAScript / JavaScript

For the purpose of static graphics, we can ignore the scripting portion of that. But even without that, implementing both a good XML and CSS parser is a lot of work.

Then SVG on top. SVG is so complex that different implementations of SVG disagree how an image should look. Especially if that image contains <text>, as it depends on the system. What some of you probably learned by now is that if you want to have a redistributable SVG file, you have to have your authoring file in Inkscape, Illustrator, Batik, ... and you have your final file which has all texts converted to paths. Otherwise, the file will look very different on each machine. An example:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="150" viewBox="0 0 400 150">
  <rect x="50" y="50" width="300" height="50" fill="red" />
  <text x="50" y="100" style="font-family: monospace; font-size: 50;">Hello</text>
</svg>
Enter fullscreen mode Exit fullscreen mode

How will this look in different browsers? Let's test!

Windows 10, Edge Void Linux, Chrome Void Linux, Firefox

🤔 That didn't go as expected. I thought that at least both files on my Linux machine look the same, but it seems like Firefox doesn't like the font-size specification, while Chrome and Edge do.

And there are more and more edge cases which make implementation SVG too complex. Files can be pulled in from external sources via xlink, file contents could be built by complex scripts, and so on. But even simpler files might break.

#FF000080 isn't a valid SVG color, but it's a valid HTML color. Chrome, Firefox and Edge show us a half-transparent red, while Inkscape and QtSvg show a black square.

All of this stuff made me realize: XML is meant to be an authoring file for vector graphics like xcf or psd which contains not only the final graphic information, but also how that graphic is constructed piece by piece.

What we really need is a format like PNG for vector graphics. Compact, versatile and simple to implement. What most of us don't need are vector graphic animations or vector graphic applications. What we definitly don't need is a vector graphic format that can do raw sockets.

After the reasearch I did to implement SVG in Zig, I was disappointed and angry that stuff like vector graphics is so complex and in my stubbornness I decided:

I'll make my own vector format, without blackjack and hookers.

Enter TinyVG

I created a new format called Tiny Vector Graphics or short TinyVG that tries to have 95% of the features we actually need from SVG (so shapes, colors, gradients, scalability) but not have all the things we typically don't need (animations, scripting, external resources, hierarchical document structure, ...).

As recent developments shows that complexity makes things susceptible to vulnerabilities, so it seems that going the simple route (like QOI did) is the right way.

Prior Art

So before implementing a new graphics format, I looked at the things we have today:

  • SVG is abundant. It is used nearly everywhere in Web and UI. Complexity is over the top.
  • HVIF seems promising, but the lack of documentation is shying me away
  • DXF is mostly used in CAD, but doesn't seem to have widespread support outside of that realm.

Design Goals

Looking at these formats made me set my design goals:

  • Compact binary encoding (Make it smaller than SVG)
  • Suitable for different platforms
    • GPU / Games
    • CPU / Desktop Applications
    • Web
    • Embedded
  • Support a reasonable subset of SVG
  • Suitable for different use cases
    • Application/toolbar icons
    • Graphs and diagrams
    • Comics, mangas, pictures and other kinds of art
  • Low implementation complexity (Make it simpler than SVG)

Triggered by a discussion in the Zig discord, I started to work on TinyVG in September 2020 and in May 2021 I got it to a state where I could live with it and use it for things in other projects:

Dunstwolke Android Application

But then Dominic Szablewski published the The Quite OK Image Format and showed me that there was interest in simpler formats. It inspired and motivated me to push for TinyVG completion and I got back to the project.

The project was already in an OK state, but I wanted to go better. I refactored pretty much everything, streamlined the design of the format and got some things right.

This work made TinyVG smaller and more flexible than before and running benchmarks with a SVG converter showed me that I was on the right path.

I got the file size down to 40% compared to optimized SVG while retaining visual fidelity:

Comparison between SVG and TVG

The three images you see here are:

  • (left) The original SVG file from the Papirus icon theme
  • (middle) My TinyVG software renderer output
  • (right) The TinyVG data rendered as SVG again

There are tiny differences in the files, but overall I'm very happy with the conversion process.

Status Quo

tiger.svg rendered with TinyVG

With this day, I release the first draft of the specification into the wild and open for review.

Using TinyVG

With the reference implementation is done and the first draft of the specification written, you can already go and try TinyVG!

On the website, you can find the following things:

Mission successful!

So let's recap if we succeeded in the goals set at the project start:

Compact binary encoding

The benchmark shows that TinyVG is between 20% and 60% of an equivalent, optimized SVG file. This means the mission was a success in that regard. ✅

Suitable for different use cases

Both the Material Design icon set as well as the Papirus one can be converted to a large degree without any losses. This means that we can render application and toolbar icons very well.

The example files on the website also show examples for a comic, a chart, graph and art.

So the planned use cases can be covered with TinyVG. ✅

Support a reasonable subset of SVG

This one is easily shown: We successfully converted a huge load of SVG files in the benchmark (roughly 3500 files) without much problems.

Perfect! ✅

Suitable for applications

There's both a CPU renderer implementation as well as a polyfill. This means we already have covered classic desktop applications as well as web content. There also is a Vulkan renderer implemented (not open source) for a older version of TinyVG, so GPU rendering also is covered.

But what about memory and cpu restricted environments like embedded platforms?

Let a photo speak for itself:

TinyVG graphics on a microcontroller

This goal: Achieved! ✅

Low implementation complexity

Make it simpler than SVG. Well, that's an easy one. But let's compare some real numbers!

The TinyVG SDK in total has roughly 4000 lines of Zig and 2000 lines of C#. The C# portion only implements only the SVG to TinyVG conversion, utilizing the System.Xml.XmlSerializer class for parsing XML. This means that there is low semantic checking and zero rendering involved. The Zig implementation though implements parsing the text and binary representation of TinyVG, and provides a software renderer as well. The code also includes the command line tools and native bindings.

To compare this to a SVG implementation, I've chosen libresvg, a Rust library to render SVG files. RazrFalcon claims that the whole SVG implementatio is roughly 50kLOC with all dependencies.

This shows that TinyVG can be fully implemented in a lower level language (Zig) with a low amount of code, while SVG requires substantially more code in languages with even a higher language of abstraction (C#, Rust).

Also the TinyVG spec is 14 pages long and won't grow by a lot if done more precise while the SVG 1.1 spec alone is 260 pages long, excluding the specifications for CSS, XML and ECMA-Script.

So I'd say: This is definitly a success! ✅

Contributing and Community

If you are interested in TinyVG, you have the following option:

Frequently asked questions

Did you have problems implementing TinyVG?

Not

Alt Text

At

Alt Text
Alt Text

All.

Alt Text
Alt Text

See!

Alt Text

Spoiler: This section isn't really a FAQ, but I wanted to share these images anyways

Top comments (9)

Collapse
 
dylangtech profile image
Dylan Green

I've never really looking too much into vector graphics from a programming point of view until I started looking to make a website that was gonna be on a variety of screens. I found the SVG to be rather underwhelming for the reasons many here talked about. Like most things in web development, a lot of it is tied to very old standards from as early as Netscape Navigator. While the underlying implementation is free to improve, the effort to phase older standards out in favor of newer ones can be chaotic. Just look at Silverlight and especially Flash. It's gonna take a lot of effort for any serious replacement to come forward, even if it is objectively better. I like your project though! Very neat!

Collapse
 
supertobi profile image
supertobi
  • Yes, SVG sucks in many ways.
  • Yes, SVG should be replaced with something lighter for desktop icons, UIs...
  • But if you compare filesize you should compare SVGZ with with your files.
  • The example with the invalid SVG color "#FF000080" is a bad example. Different handling of invalid files is not a bug but a design decision to show some thing at all.

  • Have you looked at the old SVG-Mobile?
    w3.org/TR/2003/REC-SVGMobile-20030...

Btw. All well known vector file formats have the tendency to become to monsters over time. Ave a look at PS, EPS, PDF and font file formats. And most of the time Adobe was involved.

Collapse
 
orent profile image
orent

This reminds me a bit of the relationship between PS and PDF. It removed the Turing-complete stack language out of PS and just recorded its output commands.

PDF was subsequently bloatified, but it started as a simplified PS.

Collapse
 
joakim85 profile image
joakim

I appreciate your work on a new vector format! I think SVG leaves a lot to be desired for several use cases.

I have a slight issue with your bashing of SVG in general, though. It seems unnecessary, especially since your example of the text element not displaying correctly in Firefox seems to be due to a missing font-size unit...

without px
with px

Collapse
 
photopea profile image
Photopea

BTW. I think all binary formats today should be built on top of Protocol Buffers. PBs is the "binary JSON", and implementing the format decoder can be 2x faster.

Collapse
 
zellyn profile image
Zellyn Hunter

Out of curiosity, did you find github.com/google/iconvg in your searches? Seems like it's aiming at some of the same use-cases.

Collapse
 
aquaductape profile image
Caleb Taylor

This is cool. I'm excited when TinyVG renderer will have same fidelity as SVG renderer, cuz it looks pretty blurry.

Collapse
 
xq profile image
Felix "xq" Queißner

It isn't blurry at all, but you're mostly looking at screenshots of vector graphics, which are scaled down/up, so the pixel graphics will be obviously blurry.

See this image for example: tiger.png

You have to open it with 100% scaling, otherwise it will look blurry because of sampling problems

Collapse
 
xxgreg profile image
Greg Lowe

Ian Hickson has a straw man spec, and implementation of a similar format here.

flutter.dev/go/vector-graphics