The 1k Notebook (part I)

Introduction

Everything started just after JS1k 2012, “Love”. I was making some experiments with the possibility to implement a full parametric vector-font in canvas. The first approach was a very basic font face, made with straight vectors. Write in the input field to update the font rendering.

The encoding of this font was only 161 chars in total, including the string declaration with the split(0) to make it as array of strings.

f='GIOMJL0AMOIG0IGMO0COMGI0OMGILJ0CBN0OMGIUS0AMGIO0GHN0GHTS0AMIKO0BN0MGHNHIO0MGIO0GIOMG0SGIOM0UIGMO0MGI0IGJLOM0BNO0GMOI0GJNLI0GMNHNOI0GOKMI0GMOIUS0GIMO'.split(0);

Every letter is a set of lines drawn in sequence. The start and end points of every line are encoded using the next two dimensional grid definition, common for every glyph:


The code to draw the characters from the data is very simple. Loop through all the chars encoded, drawing lines from point to point decoded. There are four special cases, for chars i,j,t and f. The code draws an additional line for those ones to finish the drawing.

var P=f[t.charCodeAt(i)-65];
if (P) {
	for (j=1;j<P.length;j++) 
		drawline(P.charCodeAt(j-1)-65,P.charCodeAt(j)-65);
	if (t[i]==='I'||t[i]==='J') drawline(3,4);
	if (t[i]==='F'||t[i]==='T') drawline(3,5);
}

With this experiment was clear the method got possibilities. Total code size was much lower than 1024, so why not try it with a more complex font face?

The Hershey font

Once JS1k 2013 was announced, I came back to the experiments and tried to make something to submit. More or less at the same time, Jari Komppa released the demo Litterae Finis, where some scripting fonts appeared in text mode. He made a breakdown, explaining the secret fonts used, the Hershey fonts.

The font collection was developed in 1967 by Dr. A. V. Hershey. The original data format is really cryptic, fortunately Jari developed a decoder and made it available to the public. The script face was perfect for the task, a handwriting font with a single vector trace.

Hershey Script

The Hershey script font data for the character “b” is an array of coords. Every pair of numbers is a (x,y) couple. The vector lines are defined by two consecutive couples, this helps a lot to draw fonts with non continuous traces. But in my case the target is to have a continuous single trace, so a very fast compression can be achieved by removing this:

c67 = [0,20,2,17,2,17,5,12,5,12,6,10,6,10,7,7,7,7,7,5,7,5,6,4,6,4,4,5,4,5,3,7,3,7,2,11,2,11,1,18,1,18,1,24,1,24,2,25,2,25,3,25,3,25,5,24,5,24,7,22,7,22,8,19,8,19,8,16,8,16,9,20,9,20,10,21,10,21,12,21,12,21,14,20];  // before

c67 = [0,20,2,17,5,12,6,10,7,7,7,5,6,4,4,5,3,7,2,11,1,18,1,24,2,25,3,25,5,24,7,22,8,19,8,16,9,20,10,21,12,21,14,20];  // after

Next steps to continue compressing the data are to split the array in two (x and y coordinates separated) and apply a delta difference between consecutive coordinates. The drawing algorithm will make a cumulative sum to generate the next coordinate.

cb=[0,20,2,17,5,12,6,10,7,7,7,5,6,4,4,5,3,7,2,11,1,18,1,24,2,25,3,25,5,24,7,22,8,19,8,16,9,20,10,21,12,21,14,20];  
// before

xb=[ 0, 2, 3, 1, 1, 0,-1,-2,-1,-1,-1,0,1,1, 2, 2, 1, 0,1,1,2, 2]; 
yb=[20,-3,-5,-2,-3,-2,-1, 1, 2, 4, 7,6,1,0,-1,-2,-3,-3,4,1,0,-1];  
// after (22 coord pairs)

The first coordinate of every glyph is always a jump to the drawing starting point. This is controlled by the drawing algorithm with an special case coded for the first coordinates.


Try clicking at the nodes in the previous canvas. The details on how the “b” char is encoded are shown. We got a data set with all (x,y) values in a 4 bits range (-8 to 7). Before encoding the coordinates, they’re converted to only positive ranges by adding 8. In this way they fit perfectly in 4 bits (0 to 15). The two couples of every vector are stored in an Unicode char (16 bits). After doing this for the whole 26 glyph set (from A to Z), we got:

F="靶杨楹窊骩ꢧ隢綋馘ꞗꖈ0ࢥ뎖閆睩穼美馘Ꞧ閅鲙ꢧ0皇睨楹窊骩뢶ꖈ0靶杨楹窊骩ꢧ隢ꊢ湮綋馘ꞗꖈ0ᮧ鞖虷硩窋骩ꢧ鞥0壃ꖖ閆睩穯潟箊馧閐馨ꞗꖈ0靶杨楹窊骩ꢧ鞡潯筺楷蚕떶Ꞷ떈0ࢥ뎖閆睩穼繿覕隥Ꞩ馊箊馘ꞗꖈ0ࢤ溊馘ꞗꖈ0袤湮湺楷蚕떶Ꞷ떈0ࢥ뎖閆睩穼繿覕隥Ꞩ馊楘ꦛ馘ꞗꖈ0ࢥ뎖閆睩穼美馘ꞗꖈ0ࢥꞙ襼箕隥Ꞩ馉类閖ꖧꢙ詻誙颧鞥0ࢥꞙ襼箕隥Ꞩ馊箊馘ꞗꖈ0摨楹窊骩ꢧ鞖虶杹誚ꦸꞗ0䢥陼湮溢ꊢ隧ꢩ骊穹楇ꦸ랧떈0靶杨楹窊骩ꢧ끻浟箊馧閁Ꞷ떈0ࢥ隊뢙詻覙颧鞥0ࢥ隊ꮚ詩䞩좧鞥0ࢥ꒕ꉮ湮誙ꢧ鞥0ࢤ溊馨Ꞧꖕ溊馘ꞗꖈ0ࢤ綋馘랦閅鲙ꢧ0㑪箊骨Ꞧꉮ誙ꢧꚕ薜馨ꞈ0ࢥꞨ馏馸뚥啷桹佹桷0ࢤ溊馨Ꞧꖕ湮湺楷蚕떶Ꞷ떈0ࢥꞨꪊ穪妩骋筺楷蚕떶억".split(0);

300 unicode chars, this means 600 bytes. Still too big, it was clear further compression techniques were needed. In the following animated drawing of every glyph, details as the initial kerning jump and single-trace style of the font are shown.



Check the jump to the right made at the beginning by characters “a”, “c” or “g”. This is also happening with “f”, “j” and “p”, braking the continuous kerning of the font. In these cases, glyph coordinates were modified by hand to fix it.

How to reach the 1024 bytes target with further compression techniques and many more things implemented in this demo, in the next chapter. Thanks for reading!

4 thoughts on “The 1k Notebook (part I)

  1. Computational fonts for the web | Experimental: Libre Graphics magazine

  2. Creative approaches to font display on the web | Making Libre Graphics Magazine

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>