1
"""Main TTX application, Mac-only"""
4
#make sure we don't lose events to SIOUX
6
MacOS.EnableAppswitch(-1)
10
Qd.SetCursor(Qd.GetCursor(QuickDraw.watchCursor).data)
14
Qd.SetCursor(Qd.qd.arrow)
19
LOGFILENAME = "TTX errors"
20
PREFSFILENAME = "TTX preferences"
21
DEFAULTXMLOUTPUT = ":XML output"
22
DEFAULTTTOUTPUT = ":TrueType output"
26
import MiniAEFrame, AppleEvents
34
from fontTools import ttLib, version
35
from fontTools.ttLib import xmlImport
36
from fontTools.ttLib.macUtils import ProgressBar
39
TTX - The free TrueType to XML to TrueType converter
41
Copyright 1999-2001, Just van Rossum (Letterror)
42
just@letterror.com""" % version
45
class TTX(FrameWork.Application, MiniAEFrame.AEServer):
48
FrameWork.Application.__init__(self)
49
MiniAEFrame.AEServer.__init__(self)
50
self.installaehandler(
51
AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, self.do_nothing)
52
self.installaehandler(
53
AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, self.do_nothing)
54
self.installaehandler(
55
AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments, self.handle_opendocumentsevent)
56
self.installaehandler(
57
AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, self.handle_quitevent)
59
def idle(self, event):
62
def makeusermenus(self):
63
m = FrameWork.Menu(self.menubar, "File")
64
FrameWork.MenuItem(m, "Open...", "O", self.domenu_open)
65
FrameWork.Separator(m)
66
FrameWork.MenuItem(m, "Quit", "Q", self._quit)
68
def do_about(self, *args):
69
EasyDialogs.Message(abouttext)
71
def handle_quitevent(self, *args, **kwargs):
74
def domenu_open(self, *args):
75
fss, ok = macfs.StandardGetFile()
77
self.opendocument(fss.as_pathname())
79
def handle_opendocumentsevent(self, docs, **kwargs):
80
if type(docs) <> type([]):
83
fss, a = doc.Resolve()
84
path = fss.as_pathname()
85
self.opendocument(path)
87
def opendocument(self, path):
88
filename = os.path.basename(path)
89
filetype = guessfiletype(path)
90
handler = getattr(self, "handle_%s_file" % filetype)
93
def handle_xml_file(self, path):
95
makesuitcase = int(prefs.get("makesuitcases", 0))
96
dstfolder = prefs.get("ttoutput", DEFAULTTTOUTPUT)
97
if not os.path.exists(dstfolder):
99
srcfilename = dstfilename = os.path.basename(path)
100
if dstfilename[-4:] in (".ttx", ".xml"):
101
dstfilename = dstfilename[:-4]
102
if dstfilename[-4:] not in (".TTF", ".ttf"):
103
dstfilename = dstfilename + ".TTF"
104
dst = os.path.join(dstfolder, dstfilename)
108
# see if the destination file is writable,
109
# otherwise we'll get an error waaay at the end of
110
# the parse procedure
111
testref = Res.FSpOpenResFile(macfs.FSSpec(dst), 3) # read-write
112
except Res.Error, why:
113
if why[0] <> -43: # file not found
114
EasyDialogs.Message("Can't create '%s'; file already open" % dst)
117
Res.CloseResFile(testref)
122
EasyDialogs.Message("Can't create '%s'; file already open" % dst)
126
pb = ProgressBar("Reading TTX file '%s'..." % srcfilename)
129
tt.importXML(path, pb)
130
pb.setlabel("Compiling and saving...")
131
tt.save(dst, makesuitcase)
135
def handle_datafork_file(self, path):
137
dstfolder = prefs.get("xmloutput", DEFAULTXMLOUTPUT)
138
if not os.path.exists(dstfolder):
140
filename = os.path.basename(path)
141
pb = ProgressBar("Dumping '%s' to XML..." % filename)
142
if filename[-4:] in (".TTF", ".ttf"):
143
filename = filename[:-4]
144
filename = filename + ".ttx"
145
dst = os.path.join(dstfolder, filename)
147
tt = ttLib.TTFont(path)
152
def handle_resource_file(self, path):
154
dstfolder = prefs.get("xmloutput", DEFAULTXMLOUTPUT)
155
if not os.path.exists(dstfolder):
157
filename = os.path.basename(path)
158
fss = macfs.FSSpec(path)
160
resref = Res.FSpOpenResFile(fss, 1) # read-only
163
Res.UseResFile(resref)
166
n = Res.Count1Resources("sfnt")
167
for i in range(1, n+1):
168
res = Res.Get1IndResource('sfnt', i)
169
resid, restype, resname = res.GetResInfo()
171
resname = filename + `i`
172
pb = ProgressBar("Dumping '%s' to XML..." % resname)
173
dst = os.path.join(dstfolder, resname + ".ttx")
175
tt = ttLib.TTFont(path, i)
180
Res.CloseResFile(resref)
182
def handle_python_file(self, path):
184
#print "python", path
186
def handle_unknown_file(self, path):
187
EasyDialogs.Message("Cannot open '%s': unknown file kind" % os.path.basename(path))
189
def do_nothing(self, *args, **kwargs):
192
def mainloop(self, mask=FrameWork.everyEvent, wait=0):
194
while not self.quitting:
196
self.do1event(mask, wait)
197
except self.__class__:
198
# D'OH! FrameWork tries to quit us on cmd-.!
200
except KeyboardInterrupt:
202
except ttLib.xmlImport.xml_parse_error, why:
204
"An error occurred while parsing the XML file:\n" + why)
206
exc = traceback.format_exception(sys.exc_type, sys.exc_value, None)[0]
207
exc = string.strip(exc)
208
EasyDialogs.Message("An error occurred!\n%s\n[see the logfile '%s' for details]" %
210
traceback.print_exc()
212
def do_kHighLevelEvent(self, event):
214
AE.AEProcessAppleEvent(event)
218
def guessfiletype(path):
219
#if path[-3:] == ".py":
224
if data[:5] == "<?xml":
226
elif data[:4] in ("\000\001\000\000", "OTTO", "true"):
229
# assume res fork font
230
fss = macfs.FSSpec(path)
232
resref = Res.FSpOpenResFile(fss, 1) # read-only
235
Res.UseResFile(resref)
236
i = Res.Count1Resources("sfnt")
237
Res.CloseResFile(resref)
244
xmloutput: ":XML output"
245
ttoutput: ":TrueType output"
249
def getprefs(path=PREFSFILENAME):
250
if not os.path.exists(path):
252
f.write(default_prefs)
255
lines = f.readlines()
258
if line[-1:] == "\n":
261
name, value = re.split(":", line, 1)
262
prefs[string.strip(name)] = eval(value)
271
sys.stdin = dummy_stdin()
273
# redirect all output to a log file
274
sys.stdout = sys.stderr = open(LOGFILENAME, "w", 0) # unbuffered
275
print "Starting TTX at " + time.ctime(time.time())
282
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
283
# clues for BuildApplication/MacFreeze.
285
# These modules somehow get imported, but we don't want/have them:
287
# macfreeze: exclude msvcrt
288
# macfreeze: exclude W
289
# macfreeze: exclude SOCKS
290
# macfreeze: exclude TERMIOS
291
# macfreeze: exclude termios
292
# macfreeze: exclude icglue
293
# macfreeze: exclude ce
295
# these modules are imported dynamically, so MacFreeze won't see them:
297
# macfreeze: include fontTools.ttLib.tables._c_m_a_p
298
# macfreeze: include fontTools.ttLib.tables._c_v_t
299
# macfreeze: include fontTools.ttLib.tables._f_p_g_m
300
# macfreeze: include fontTools.ttLib.tables._g_a_s_p
301
# macfreeze: include fontTools.ttLib.tables._g_l_y_f
302
# macfreeze: include fontTools.ttLib.tables._h_d_m_x
303
# macfreeze: include fontTools.ttLib.tables._h_e_a_d
304
# macfreeze: include fontTools.ttLib.tables._h_h_e_a
305
# macfreeze: include fontTools.ttLib.tables._h_m_t_x
306
# macfreeze: include fontTools.ttLib.tables._k_e_r_n
307
# macfreeze: include fontTools.ttLib.tables._l_o_c_a
308
# macfreeze: include fontTools.ttLib.tables._m_a_x_p
309
# macfreeze: include fontTools.ttLib.tables._n_a_m_e
310
# macfreeze: include fontTools.ttLib.tables._p_o_s_t
311
# macfreeze: include fontTools.ttLib.tables._p_r_e_p
312
# macfreeze: include fontTools.ttLib.tables._v_h_e_a
313
# macfreeze: include fontTools.ttLib.tables._v_m_t_x
314
# macfreeze: include fontTools.ttLib.tables.L_T_S_H_
315
# macfreeze: include fontTools.ttLib.tables.O_S_2f_2
316
# macfreeze: include fontTools.ttLib.tables.T_S_I__0
317
# macfreeze: include fontTools.ttLib.tables.T_S_I__1
318
# macfreeze: include fontTools.ttLib.tables.T_S_I__2
319
# macfreeze: include fontTools.ttLib.tables.T_S_I__3
320
# macfreeze: include fontTools.ttLib.tables.T_S_I__5
321
# macfreeze: include fontTools.ttLib.tables.C_F_F_