diff --git a/Mac/TTX.py b/Mac/TTX.py index cecaba5e7..639b40e7d 100644 --- a/Mac/TTX.py +++ b/Mac/TTX.py @@ -1 +1,325 @@ -execfile("TTXMain.py") +"""Main TTX application, Mac-only""" + + +__version__ = "1.0a7" + + +#make sure we don't lose events to SIOUX +import MacOS +MacOS.EnableAppswitch(-1) + +def SetWatchCursor(): + import Qd, QuickDraw + Qd.SetCursor(Qd.GetCursor(QuickDraw.watchCursor).data) + +def SetArrowCursor(): + import Qd + Qd.SetCursor(Qd.qd.arrow) + +SetWatchCursor() + +# a few constants +LOGFILENAME = "TTX errors" +PREFSFILENAME = "TTX preferences" +DEFAULTXMLOUTPUT = ":XML output" +DEFAULTTTOUTPUT = ":TrueType output" + + +import FrameWork +import MiniAEFrame, AppleEvents +import EasyDialogs +import Res +import macfs +import os +import sys, time +import re, string +import traceback +from fontTools import ttLib +from fontTools.ttLib import xmlImport +from fontTools.ttLib.macUtils import ProgressBar + +abouttext = """\ +TTX - The free TrueType to XML to TrueType converter +(version %s) +Copyright 1999-2000, Just van Rossum (Letterror) +just@letterror.com""" % __version__ + + +class TTX(FrameWork.Application, MiniAEFrame.AEServer): + + def __init__(self): + FrameWork.Application.__init__(self) + MiniAEFrame.AEServer.__init__(self) + self.installaehandler( + AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, self.do_nothing) + self.installaehandler( + AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, self.do_nothing) + self.installaehandler( + AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments, self.handle_opendocumentsevent) + self.installaehandler( + AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, self.handle_quitevent) + + def idle(self, event): + SetArrowCursor() + + def makeusermenus(self): + m = FrameWork.Menu(self.menubar, "File") + FrameWork.MenuItem(m, "Open...", "O", self.domenu_open) + FrameWork.Separator(m) + FrameWork.MenuItem(m, "Quit", "Q", self._quit) + + def do_about(self, *args): + EasyDialogs.Message(abouttext) + + def handle_quitevent(self, *args, **kwargs): + self._quit() + + def domenu_open(self, *args): + fss, ok = macfs.StandardGetFile() + if ok: + self.opendocument(fss.as_pathname()) + + def handle_opendocumentsevent(self, docs, **kwargs): + if type(docs) <> type([]): + docs = [docs] + for doc in docs: + fss, a = doc.Resolve() + path = fss.as_pathname() + self.opendocument(path) + + def opendocument(self, path): + filename = os.path.basename(path) + filetype = guessfiletype(path) + handler = getattr(self, "handle_%s_file" % filetype) + handler(path) + + def handle_xml_file(self, path): + prefs = getprefs() + makesuitcase = int(prefs.get("makesuitcases", 0)) + dstfolder = prefs.get("ttoutput", DEFAULTTTOUTPUT) + if not os.path.exists(dstfolder): + os.mkdir(dstfolder) + srcfilename = dstfilename = os.path.basename(path) + if dstfilename[-4:] in (".ttx", ".xml"): + dstfilename = dstfilename[:-4] + if dstfilename[-4:] not in (".TTF", ".ttf"): + dstfilename = dstfilename + ".TTF" + dst = os.path.join(dstfolder, dstfilename) + + if makesuitcase: + try: + # see if the destination file is writable, + # otherwise we'll get an error waaay at the end of + # the parse procedure + testref = Res.FSpOpenResFile(macfs.FSSpec(dst), 3) # read-write + except Res.Error, why: + if why[0] <> -43: # file not found + EasyDialogs.Message("Can't create '%s'; file already open" % dst) + return + else: + Res.CloseResFile(testref) + else: + try: + f = open(dst, "wb") + except IOError, why: + EasyDialogs.Message("Can't create '%s'; file already open" % dst) + return + else: + f.close() + pb = ProgressBar("Reading TTX file '%s'..." % srcfilename) + try: + tt = ttLib.TTFont() + tt.importXML(path, pb) + pb.setlabel("Compiling and saving...") + tt.save(dst, makesuitcase) + finally: + pb.close() + + def handle_datafork_file(self, path): + prefs = getprefs() + dstfolder = prefs.get("xmloutput", DEFAULTXMLOUTPUT) + if not os.path.exists(dstfolder): + os.mkdir(dstfolder) + filename = os.path.basename(path) + pb = ProgressBar("Dumping '%s' to XML..." % filename) + if filename[-4:] in (".TTF", ".ttf"): + filename = filename[:-4] + filename = filename + ".ttx" + dst = os.path.join(dstfolder, filename) + try: + tt = ttLib.TTFont(path) + tt.saveXML(dst, pb) + finally: + pb.close() + + def handle_resource_file(self, path): + prefs = getprefs() + dstfolder = prefs.get("xmloutput", DEFAULTXMLOUTPUT) + if not os.path.exists(dstfolder): + os.mkdir(dstfolder) + filename = os.path.basename(path) + fss = macfs.FSSpec(path) + try: + resref = Res.FSpOpenResFile(fss, 1) # read-only + except: + return "unknown" + Res.UseResFile(resref) + pb = None + try: + n = Res.Count1Resources("sfnt") + for i in range(1, n+1): + res = Res.Get1IndResource('sfnt', i) + resid, restype, resname = res.GetResInfo() + if not resname: + resname = filename + `i` + pb = ProgressBar("Dumping '%s' to XML..." % resname) + dst = os.path.join(dstfolder, resname + ".ttx") + try: + tt = ttLib.TTFont(path, i) + tt.saveXML(dst, pb) + finally: + pb.close() + finally: + Res.CloseResFile(resref) + + def handle_python_file(self, path): + pass + #print "python", path + + def handle_unknown_file(self, path): + EasyDialogs.Message("Cannot open '%s': unknown file kind" % os.path.basename(path)) + + def do_nothing(self, *args, **kwargs): + pass + + def mainloop(self, mask=FrameWork.everyEvent, wait=0): + self.quitting = 0 + while not self.quitting: + try: + self.do1event(mask, wait) + except self.__class__: + # D'OH! FrameWork tries to quit us on cmd-.! + pass + except KeyboardInterrupt: + pass + except ttLib.xmlImport.xml_parse_error, why: + EasyDialogs.Message( + "An error occurred while parsing the XML file:\n" + why) + except: + exc = traceback.format_exception(sys.exc_type, sys.exc_value, None)[0] + exc = string.strip(exc) + EasyDialogs.Message("An error occurred!\n%s\n[see the logfile '%s' for details]" % + (exc, LOGFILENAME)) + traceback.print_exc() + + def do_kHighLevelEvent(self, event): + import AE + AE.AEProcessAppleEvent(event) + + + +def guessfiletype(path): + #if path[-3:] == ".py": + # return "python" + f = open(path, "rb") + data = f.read(21) + f.close() + if data == "": + return "xml" + elif data[:4] in ("\000\001\000\000", "OTTO", "true"): + return "datafork" + else: + # assume res fork font + fss = macfs.FSSpec(path) + try: + resref = Res.FSpOpenResFile(fss, 1) # read-only + except: + return "unknown" + Res.UseResFile(resref) + i = Res.Count1Resources("sfnt") + Res.CloseResFile(resref) + if i > 0: + return "resource" + return "unknown" + + +default_prefs = """\ +xmloutput: ":XML output" +ttoutput: ":TrueType output" +makesuitcases: 1 +""" + +def getprefs(path=PREFSFILENAME): + if not os.path.exists(path): + f = open(path, "w") + f.write(default_prefs) + f.close() + f = open(path) + lines = f.readlines() + prefs = {} + for line in lines: + if line[-1:] == "\n": + line = line[:-1] + try: + name, value = re.split(":", line, 1) + prefs[string.strip(name)] = eval(value) + except: + pass + return prefs + + +class dummy_stdin: + def readline(self): + return "" +sys.stdin = dummy_stdin() + +# redirect all output to a log file +sys.stdout = sys.stderr = open(LOGFILENAME, "w", 0) # unbuffered +print "Starting TTX at " + time.ctime(time.time()) + +# fire it up! +ttx = TTX() +ttx.mainloop() + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# clues for BuildApplication/MacFreeze. +# +# These modules somehow get imported, but we don't want/have them: +# +# macfreeze: exclude msvcrt +# macfreeze: exclude W +# macfreeze: exclude SOCKS +# macfreeze: exclude TERMIOS +# macfreeze: exclude termios +# macfreeze: exclude icglue +# macfreeze: exclude ce +# +# these modules are imported dynamically, so MacFreeze won't see them: +# +# macfreeze: include fontTools.ttLib.tables._c_m_a_p +# macfreeze: include fontTools.ttLib.tables._c_v_t +# macfreeze: include fontTools.ttLib.tables._f_p_g_m +# macfreeze: include fontTools.ttLib.tables._g_a_s_p +# macfreeze: include fontTools.ttLib.tables._g_l_y_f +# macfreeze: include fontTools.ttLib.tables._h_d_m_x +# macfreeze: include fontTools.ttLib.tables._h_e_a_d +# macfreeze: include fontTools.ttLib.tables._h_h_e_a +# macfreeze: include fontTools.ttLib.tables._h_m_t_x +# macfreeze: include fontTools.ttLib.tables._k_e_r_n +# macfreeze: include fontTools.ttLib.tables._l_o_c_a +# macfreeze: include fontTools.ttLib.tables._m_a_x_p +# macfreeze: include fontTools.ttLib.tables._n_a_m_e +# macfreeze: include fontTools.ttLib.tables._p_o_s_t +# macfreeze: include fontTools.ttLib.tables._p_r_e_p +# macfreeze: include fontTools.ttLib.tables._v_h_e_a +# macfreeze: include fontTools.ttLib.tables._v_m_t_x +# macfreeze: include fontTools.ttLib.tables.L_T_S_H_ +# macfreeze: include fontTools.ttLib.tables.O_S_2f_2 +# macfreeze: include fontTools.ttLib.tables.T_S_I__0 +# macfreeze: include fontTools.ttLib.tables.T_S_I__1 +# macfreeze: include fontTools.ttLib.tables.T_S_I__2 +# macfreeze: include fontTools.ttLib.tables.T_S_I__3 +# macfreeze: include fontTools.ttLib.tables.T_S_I__5 +# macfreeze: include fontTools.ttLib.tables.C_F_F_ + diff --git a/Mac/TTXMain.py b/Mac/TTXMain.py deleted file mode 100644 index 5de03f049..000000000 --- a/Mac/TTXMain.py +++ /dev/null @@ -1,325 +0,0 @@ -"""Main TTX application, Mac-only""" - - -__version__ = "1.0a6" - - -#make sure we don't lose events to SIOUX -import MacOS -MacOS.EnableAppswitch(-1) - -def SetWatchCursor(): - import Qd, QuickDraw - Qd.SetCursor(Qd.GetCursor(QuickDraw.watchCursor).data) - -def SetArrowCursor(): - import Qd - Qd.SetCursor(Qd.qd.arrow) - -SetWatchCursor() - -# a few constants -LOGFILENAME = "TTX errors" -PREFSFILENAME = "TTX preferences" -DEFAULTXMLOUTPUT = ":XML output" -DEFAULTTTOUTPUT = ":TrueType output" - - -import FrameWork -import MiniAEFrame, AppleEvents -import EasyDialogs -import Res -import macfs -import os -import sys, time -import re, string -import traceback -from fontTools import ttLib -from fontTools.ttLib import xmlImport -from fontTools.ttLib.macUtils import ProgressBar - -abouttext = """\ -TTX - The free TrueType to XML to TrueType converter -(version %s) -Copyright 1999-2000, Just van Rossum (Letterror) -just@letterror.com""" % __version__ - - -class TTX(FrameWork.Application, MiniAEFrame.AEServer): - - def __init__(self): - FrameWork.Application.__init__(self) - MiniAEFrame.AEServer.__init__(self) - self.installaehandler( - AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, self.do_nothing) - self.installaehandler( - AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, self.do_nothing) - self.installaehandler( - AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments, self.handle_opendocumentsevent) - self.installaehandler( - AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, self.handle_quitevent) - - def idle(self, event): - SetArrowCursor() - - def makeusermenus(self): - m = FrameWork.Menu(self.menubar, "File") - FrameWork.MenuItem(m, "Open...", "O", self.domenu_open) - FrameWork.Separator(m) - FrameWork.MenuItem(m, "Quit", "Q", self._quit) - - def do_about(self, *args): - EasyDialogs.Message(abouttext) - - def handle_quitevent(self, *args, **kwargs): - self._quit() - - def domenu_open(self, *args): - fss, ok = macfs.StandardGetFile() - if ok: - self.opendocument(fss.as_pathname()) - - def handle_opendocumentsevent(self, docs, **kwargs): - if type(docs) <> type([]): - docs = [docs] - for doc in docs: - fss, a = doc.Resolve() - path = fss.as_pathname() - self.opendocument(path) - - def opendocument(self, path): - filename = os.path.basename(path) - filetype = guessfiletype(path) - handler = getattr(self, "handle_%s_file" % filetype) - handler(path) - - def handle_xml_file(self, path): - prefs = getprefs() - makesuitcase = int(prefs.get("makesuitcases", 0)) - dstfolder = prefs.get("ttoutput", DEFAULTTTOUTPUT) - if not os.path.exists(dstfolder): - os.mkdir(dstfolder) - srcfilename = dstfilename = os.path.basename(path) - if dstfilename[-4:] in (".ttx", ".xml"): - dstfilename = dstfilename[:-4] - if dstfilename[-4:] not in (".TTF", ".ttf"): - dstfilename = dstfilename + ".TTF" - dst = os.path.join(dstfolder, dstfilename) - - if makesuitcase: - try: - # see if the destination file is writable, - # otherwise we'll get an error waaay at the end of - # the parse procedure - testref = Res.FSpOpenResFile(macfs.FSSpec(dst), 3) # read-write - except Res.Error, why: - if why[0] <> -43: # file not found - EasyDialogs.Message("Can't create '%s'; file already open" % dst) - return - else: - Res.CloseResFile(testref) - else: - try: - f = open(dst, "wb") - except IOError, why: - EasyDialogs.Message("Can't create '%s'; file already open" % dst) - return - else: - f.close() - pb = ProgressBar("Reading TTX file '%s'..." % srcfilename) - try: - tt = ttLib.TTFont() - tt.importXML(path, pb) - pb.setlabel("Compiling and saving...") - tt.save(dst, makesuitcase) - finally: - pb.close() - - def handle_datafork_file(self, path): - prefs = getprefs() - dstfolder = prefs.get("xmloutput", DEFAULTXMLOUTPUT) - if not os.path.exists(dstfolder): - os.mkdir(dstfolder) - filename = os.path.basename(path) - pb = ProgressBar("Dumping '%s' to XML..." % filename) - if filename[-4:] in (".TTF", ".ttf"): - filename = filename[:-4] - filename = filename + ".ttx" - dst = os.path.join(dstfolder, filename) - try: - tt = ttLib.TTFont(path) - tt.saveXML(dst, pb) - finally: - pb.close() - - def handle_resource_file(self, path): - prefs = getprefs() - dstfolder = prefs.get("xmloutput", DEFAULTXMLOUTPUT) - if not os.path.exists(dstfolder): - os.mkdir(dstfolder) - filename = os.path.basename(path) - fss = macfs.FSSpec(path) - try: - resref = Res.FSpOpenResFile(fss, 1) # read-only - except: - return "unknown" - Res.UseResFile(resref) - pb = None - try: - n = Res.Count1Resources("sfnt") - for i in range(1, n+1): - res = Res.Get1IndResource('sfnt', i) - resid, restype, resname = res.GetResInfo() - if not resname: - resname = filename + `i` - pb = ProgressBar("Dumping '%s' to XML..." % resname) - dst = os.path.join(dstfolder, resname + ".ttx") - try: - tt = ttLib.TTFont(path, i) - tt.saveXML(dst, pb) - finally: - pb.close() - finally: - Res.CloseResFile(resref) - - def handle_python_file(self, path): - pass - #print "python", path - - def handle_unknown_file(self, path): - EasyDialogs.Message("Cannot open '%s': unknown file kind" % os.path.basename(path)) - - def do_nothing(self, *args, **kwargs): - pass - - def mainloop(self, mask=FrameWork.everyEvent, wait=0): - self.quitting = 0 - while not self.quitting: - try: - self.do1event(mask, wait) - except self.__class__: - # D'OH! FrameWork tries to quit us on cmd-.! - pass - except KeyboardInterrupt: - pass - except ttLib.xmlImport.xml_parse_error, why: - EasyDialogs.Message( - "An error occurred while parsing the XML file:\n" + why) - except: - exc = traceback.format_exception(sys.exc_type, sys.exc_value, None)[0] - exc = string.strip(exc) - EasyDialogs.Message("An error occurred!\n%s\n[see the logfile '%s' for details]" % - (exc, LOGFILENAME)) - traceback.print_exc() - - def do_kHighLevelEvent(self, event): - import AE - AE.AEProcessAppleEvent(event) - - - -def guessfiletype(path): - #if path[-3:] == ".py": - # return "python" - f = open(path, "rb") - data = f.read(21) - f.close() - if data == "": - return "xml" - elif data[:4] in ("\000\001\000\000", "OTTO", "true"): - return "datafork" - else: - # assume res fork font - fss = macfs.FSSpec(path) - try: - resref = Res.FSpOpenResFile(fss, 1) # read-only - except: - return "unknown" - Res.UseResFile(resref) - i = Res.Count1Resources("sfnt") - Res.CloseResFile(resref) - if i > 0: - return "resource" - return "unknown" - - -default_prefs = """\ -xmloutput: ":XML output" -ttoutput: ":TrueType output" -makesuitcases: 1 -""" - -def getprefs(path=PREFSFILENAME): - if not os.path.exists(path): - f = open(path, "w") - f.write(default_prefs) - f.close() - f = open(path) - lines = f.readlines() - prefs = {} - for line in lines: - if line[-1:] == "\n": - line = line[:-1] - try: - name, value = re.split(":", line, 1) - prefs[string.strip(name)] = eval(value) - except: - pass - return prefs - - -class dummy_stdin: - def readline(self): - return "" -sys.stdin = dummy_stdin() - -# redirect all output to a log file -sys.stdout = sys.stderr = open(LOGFILENAME, "w", 0) # unbuffered -print "Starting TTX at " + time.ctime(time.time()) - -# fire it up! -ttx = TTX() -ttx.mainloop() - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# clues for BuildApplication/MacFreeze. -# -# These modules somehow get imported, but we don't want/have them: -# -# macfreeze: exclude msvcrt -# macfreeze: exclude W -# macfreeze: exclude SOCKS -# macfreeze: exclude TERMIOS -# macfreeze: exclude termios -# macfreeze: exclude icglue -# macfreeze: exclude ce -# -# these modules are imported dynamically, so MacFreeze won't see them: -# -# macfreeze: include fontTools.ttLib.tables._c_m_a_p -# macfreeze: include fontTools.ttLib.tables._c_v_t -# macfreeze: include fontTools.ttLib.tables._f_p_g_m -# macfreeze: include fontTools.ttLib.tables._g_a_s_p -# macfreeze: include fontTools.ttLib.tables._g_l_y_f -# macfreeze: include fontTools.ttLib.tables._h_d_m_x -# macfreeze: include fontTools.ttLib.tables._h_e_a_d -# macfreeze: include fontTools.ttLib.tables._h_h_e_a -# macfreeze: include fontTools.ttLib.tables._h_m_t_x -# macfreeze: include fontTools.ttLib.tables._k_e_r_n -# macfreeze: include fontTools.ttLib.tables._l_o_c_a -# macfreeze: include fontTools.ttLib.tables._m_a_x_p -# macfreeze: include fontTools.ttLib.tables._n_a_m_e -# macfreeze: include fontTools.ttLib.tables._p_o_s_t -# macfreeze: include fontTools.ttLib.tables._p_r_e_p -# macfreeze: include fontTools.ttLib.tables._v_h_e_a -# macfreeze: include fontTools.ttLib.tables._v_m_t_x -# macfreeze: include fontTools.ttLib.tables.L_T_S_H_ -# macfreeze: include fontTools.ttLib.tables.O_S_2f_2 -# macfreeze: include fontTools.ttLib.tables.T_S_I__0 -# macfreeze: include fontTools.ttLib.tables.T_S_I__1 -# macfreeze: include fontTools.ttLib.tables.T_S_I__2 -# macfreeze: include fontTools.ttLib.tables.T_S_I__3 -# macfreeze: include fontTools.ttLib.tables.T_S_I__5 -# macfreeze: include fontTools.ttLib.tables.C_F_F_ -