Some lessons learned with inkscape

As I posted, I had a bit of fun designing and drawing some playing cards. This involved code, and working on SVG artwork for court cards using inkscape. I am pleased to say they are actually being made in to packs, thanks to Ivory Graphics.

Various SVG decks are at www.me.uk/cards/

Update: Yes, we have batches of A&A and FireBrick cards arriving in a week, and we'll be selling them, but we expect to give some away as well. The A&A pack is poker size and goes up to 11 (56 card deck). The FireBrick pack is bridge card size and standard 52 card deck. Ignis is the joker, of course. Watch this space.

As I explained, I was trying to go for reasonably compact SVG files, which meant all the main cards were code generated and using some hand crafted SVG paths, even using SVG symbol objects. This worked well making quite small SVG files. The complication was the court cards, which have a lot of detail.

My solution was to use inscape, and make layers - the lowest being a scan of the antique cards I have, and then layers for Gold, Red, Blue and Black. Each layer was one fill path from which I extracted the path and made part of the final SVG without all of inskscape's bloat. It worked well, and even allowed me to make them one way up only and duplicate the rotated side.

Having spent some time drawing the court cards the first time, I decided I could have done some of it better. ..

Scale, and pixels.

One issue was that some paths inkscape made had a transform, and for this reason I made each layer a single path. I included the transform inscape had chosen in the final SVG.

However, by setting inscape to use px (pixels) everywhere I was able to convince it not to scale and translate stuff, pretty much (few exceptions easily worked around).

Concatenating paths

My final SVG did not need several paths per layer though, so I concatenated them in to one path. This did not work, and it took me a few minutes to work out why.

SVG allows relative and absolute functions in the path, but you can start a path with a relative m command (move) and have several sets of co-ordinates. The first are a move and then the rest are line draw and all are relative. But as it is the start of the path the first move is actually absolute and not relative.

Why SVG has this logic I have no idea - you have to separate the first co-ordinates from the next by something, such as white space, so could have an l (line) instead of a space.

The problem is that tacking an m on the end of an existing path is relative! So I had to change it to M and find the separator and add an explicit l after the first co-ordinates if it was running-on from the initial move.

Compressing paths

At the same time I removed the spaces before and after all of the letter commands, as not needed. That worked with no problem!

Fill or stroke

One of the things I did originally was make all layers a simple fill. However, the blue layer is almost entirely line drawing on the cards, and the rest basically colouring in between the blue lines (almost none of which is actually blue). So I decided to add an extra stroked blue layer, and even a thinner stroked blue layer used for some of the fine detail on hands and eyes.

This had a much bigger effect than I expected!

For example, if you have a simple Bezier curve like this - two points and two control points:-

It translates to a path of "m 15,320.54165 c 15,-25 55,25 70,0" which I compress to "M15,320.54165c15,-25 55,25 70,0" which is tiny.  The co-ordinates are mostly whole numbers (because I am snapping to a pixel grid).

However, as soon as you stroke this to a fill, you get this:-

As you may be able to just about see, that has 12 points, each of which have control points. It makes a path like this "m 31.427734,303.5918 c -8.488979,-1.08833 -19.486526,2.61231 -25.0019528,11.80468 A 10.001,10.001 0 1 0 23.574219,325.6875 c 1.984573,-3.30762 1.612026,-2.73198 5.310547,-2.25781 3.69852,0.47417 10.101562,3.08984 16.976562,6.21484 6.875,3.125 14.221958,6.75933 22.710938,7.84766 8.488979,1.08833 19.486526,-2.61231 25.001953,-11.80469 A 10.001,10.001 0 1 0 76.425781,315.39648 c -1.984573,3.30763 -1.612026,2.73199 -5.310547,2.25782 -3.69852,-0.47417 -10.101562,-3.0918 -16.976562,-6.2168 -6.875,-3.125 -14.221958,-6.75737 -22.710938,-7.8457 z"

Not only has a 2 point Bezier become a set of 12 Beziers / arcs, but all of the points are no longer nice small integers (for obvious reasons).

Easier to use inkscape now

By changing to stroked paths and allowing lots of paths I was able to easily copy paths to make filled in areas within blue lines on other layers, and I could use path intersection and line cutting logic in inkscape to avoid rough edges or manual lining things up by eye.

This also makes it way easier to make tweaks and fix errors later. Previous I draw paths and then converted to stroke fill and union with the layer making edits almost impossible. Now I can simply edit the distinct paths.

Adding pips

The suit symbol is a feature of the clothing on all of the court cards. Previously this was just part of the artwork, but I have now made it use SVG symbols to show the suit symbol (pips) in the necessary size, rotation and locations. This means that if the suit symbol is different (as I did for an old style of cards) they are changed on the court cards as well. It also saves some space, just.

The end result?

Well, so far I have re-drawn one of the cards, which was slightly less tedious than before. The new Jack of Spades is 41k instead of the previous 119k. Note Chris Aguilar's Ace of Spades, saved from inkscape, is 137k.

What next?

I'll probably do all of the cards eventually. I am taking the opportunity to basically just do them better anyway. I feel a lot more like I have made some creative input to this project now, rather than just trying to exactly reproduce the (badly printed) antique card designs.

P.S. I have done two cards now, it is time consuming, tedious, and requires some artistic elements, but the end results are very nice so I plan to finish all 12 in due course just for good measure. They are also uploaded to wikimedia. If I do before the next batch of printed playing cards, they will be a nice version 2 of my designs.

P.P.S. I have done the Jacks now, it is hard work, but little things like inkscape has a (configurable) delay before snapping to an object, which means if you are too quick you get misaligned stuff (WTF?). It has a "cut path" function which "misses" and screws up some times. But I am getting better at using stroke to path to make parallel curved lines which looks better. Not only are we around ⅓ of the file size now, but much neater artwork. I also discovered I gave one of the Jacks the wrong colour of hat before, making these initial packs we are getting this week "limited edition" ones :-)

P.P.P.S. I have done them all now - the main problem is that real work takes priority, but I am happy with the end result and I have updated wikimedia. The history of playing cards being [badly] copied dates back around 500 years which is quite amazing really. I feel almost honoured to be a step is such a long tradition.


  1. Replies
    1. Probably next week, but we're giving some away too.

  2. Why do the svgs need to be smaller when they are already pretty small?

    1. This is as much about learning to use inkscape better, but I am a bit of a perfectionist, and the artwork was not as good as it could be the first time. Just trying to do the best job of a design of SVG cards that I can.

  3. Do you know it'd be a ridiculously useful tool for CDNs and the like if you open sourced a library that read EPS files in bulk and spat out SVG's, but not just any SVG, an optimised one for web use: https://github.com/svg/svgo


Comments are moderated purely to filter out obvious spam, but it means they may not show immediately.