Typophile

dumps every glyph in a font to a text file

fly wang0 votes

some friends of mine recommend me to ask this kind of question here

I want to write a program which takes font name as the parameter and dumps every glyph in this font to a txt file

like

bool dumpEveryGlyph(string fontName);

I am wondering if there is any API which can help me to do this? (.net API? win32 API?)

thanks very much

Here is a related thread: http://typophile.com/node/64147

The tricky thing is that not every glyph in a font must have a code point assigned, that means these unencoded glyphs cannot be represented in a plain text file.

Jens is correct. You cannot dump glyphs into a text file because a glyph means exactly nothing. It's the code points that count, because these form the link between the ASCII (or Unicode) character code you want to display and the actual piece of graphic (the glyph) that's going to be drawn. It's extremely important to understand these concepts correctly before you are going to pull off some low-level trick as you are attempting.

(This bypasses any Opentype niceties, but then again it should. Opentype features have nothing to do with codepoints -- well, at least nothing you could 'dump into a txt file'.)

There are Windows APIs -- you don't tell, which is a mortal sin, but I presume you are talking about a Windows program here -- that can return font information, but I cannot remember if I really ever bothered to get down with those. My own experimental program is firmly based on my grasp of the file format of Truetype and Opentype font files, so I can locate and extract the all-important cmap entry and work it out from there.

I see the request is from mainland China, where the preferred encoding is neither UTF-8 nor UTF-16 but GB 18030 and where the "niceties" of unicode may not be the main concern.

If you install ttx and apply ttx -i -t cmap filename.extension to your font file, giving the file filename.ttx, then the following Python code should give the desired text (on a single line) in filename.txt. Modifying the code to cut into lines, if needed, should be straightforward.

from xml.dom.minidom import *
import sys, re

f=open(sys.argv[1])
r1=re.compile(r'(.+)\.ttx , re.IGNORECASE)
foutname=r1.match(sys.argv[1]).group(1)+".txt"
fout=open(foutname,'w')

doc=parse(f)

encdng='gb18030'

str=''
cmaps=doc.getElementsByTagName('cmap_format_12')
if not cmaps:
cmaps=doc.getElementsByTagName('cmap_format_4')
maps=cmaps[0].getElementsByTagName('map')
for map in maps:
code=int(map.getAttribute('code'),16)
if code > 0x20:
str=str+unichr(code)
fout.write("%s\n" % (str.encode(encdng)))
fout.close

Of course, 'gb18030' could be replaced by 'utf-8' or 'utf-16' or some other encoding. If you copy the lines above, save to some file, say dmpcmap.py and then execute

python dmpcmap.py filename.ttx

you get the text in filename.txt

This was tested on a Mac with python26 @2.6.7_1+ucs4 on the font ST Heiti

Michel

PS The code does not check the platform because on my Mac, there are fonts without a cmap for Windows and I wanted to get an output file. Also, the code is slow on large files.

Captured from web.archive.org on 30 Jul 2018. view this capture