'''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. [Image glyphBeta] Download '''XXXXglyphs 0.9''' [http://irrational-numbers.googlecode.com/files/glyphs-0.9.zip] See also [glyphs-demo] ** Opening and closing ** 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 ====== ** Inspecting font file's properties ** 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" ** Locating the single glyph ** 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: * MOVETO x y -- set (x,y) as the current point * LINETO x y -- draw a line from current point to (x,y). (x,y) then becomes the current point * QUADTO x1 y1 x2 xy -- draw a quadratic bezier from current point, to (x1,y1) (control point) and to (x2,y2) (end-point). (x,y) then becomes the current point. 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. ** More on accessing glyphs ** 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 ====== ** Comments and Suggestions ** [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.