Glyphs is a pure-tcl library for digging into TrueType font-files.
Glyphs is able to extract the vectorial paths of each glyph - points, lines, curves.
Download XXXXglyphs 0.9 [L1 ]
This is our first quick trip; just open a .ttf, look inside and close
> package require glyphs > set fObj [glyphs open "arial.ttf"] > set ng [$fObj get numGlyphs] > puts "found $ng glyphs" > $fObj close
Reopen the .ttf file
> set fObj [glyphs open "arial.ttf"]
we already know how to get the number-of-glyphs
> set res1 [$fObj get numGlyphs] 1674
and we can also get the overall-bounding box, or where the descender-line is placed
> set res2 [$fObj get bbox] -1361 -665 4096 2060 >set res3 [$fObj get Descender] -434
but there're a lot of properties and the better way to know which properties are set is:
> set props [$fObj get] fontPath numGlyphs bbox unitsPerEm fontRevision Ascender Descender .....
WARNING: many properties may be added/removed for "glyphs 1.0"
The quickest way to locate a single glyph is through its glyph-index. You know that "arial.ttf" has 1674 glyphs, therefore you can get all glyphs from 0 to 1674.
Now let' take the 144th glyph
>set g144 [$fObj glyph 144]
As with fObj's properties, we can get some specific glyph's property:
>$g144 get index 144 >$g144 get bbox 1 0 1936 1466
The most important properties are points and commandpaths Let's take a glyph simpler than 144
>set g103 [$fObj glyph 103] >set L [$g103 get points] {99 714 1 99 1079 0 ...} {299 711 1 299 446 0 ...} {516 1556 1 516 1761 1 ...} {889 1556 1 ...}
Result looks like a list of 4 lists (4 contours).
Each contour is made of a sequence of triples x y flag.
Flag "1" means that point (x,y) is on-curve, Flag "0" means point (x,y) is the control point of a Quadratic Bezier curve.
But, how to translate these "points" in a parametric curve ?
>set L [$g103 get commandpaths] {{MOVETO 99 714} {QUADTO 99 1079 295.0 1285.5} ...} {{MOVETO 299 711} {QUADTO 299 446 441.5 293.5} ... } {{MOVETO 516 1556} {LINETO 516 1761} ... } {{MOVETO 889 1556} {LINETO 889 1761} ...}
Result is a list of (4) contours.
Each contour is made of a sequence of simple abstract commands:
It's your app's responsability to translate these 'abstract commands' in real commands. A very simple implementation for the canvas widget could be the following:
proc CommandPaths2Canvas { cvs paths } { foreach path $paths { # first command should be MOVETO foreach pCmd $path { set points [lassign $pCmd cmd] switch -- $cmd { MOVETO { ; } LINETO { $cvs create line $lastX $lastY {*}$points } QUADTO { $cvs create line $lastX $lastY {*}$points -smooth true } default { error "unrecognized path command \"$cmd\"" } } set lastX [lindex $points end-1] set lastY [lindex $points end] } } }
There's no much more to do with a single-glyph. Since it's a dynamic object, you can free space when it's no more useful
>$g133 close
but, you are not required to do it. In fact, when the 'font-file' is closed
>$fObj close #; -- THIS frees space also for all the extracted glyphs
all space is freed.
We've seen the standard way to access a glyph by-index. The major part of TrueType Fonts holds a table for converting a "character" (unicode) to index.
>$fObj unicode2glyphIndex "A" >$fObj unicode2glyphIndex "ß" ; # unicode char \u03B2 (greek letter "Beta") >$fObj unicode2glyphIndex \u03B2 ; # unicode char \u03B2 (greek letter "Beta") >$fObj numcode2glyphIndex 946 ; # it's always the greek letter "Beta" !
For your convenience, you can access a glyph, with two new methods
>$fObj glyphByUnicode "ß" ; # glyph by Unicode >$fObj glyphByCharCode 946 ; # glyph by CharCode
ABU Glyphs is a fresh new library and it requires a more mature API. I believe glyphs should be really simple to use, hiding all internal and unnecessary details.