diff --git a/Mac/TTX.py b/Mac/TTX.py new file mode 100644 index 000000000..cecaba5e7 --- /dev/null +++ b/Mac/TTX.py @@ -0,0 +1 @@ +execfile("TTXMain.py") diff --git a/Mac/TTX.rsrc.hqx b/Mac/TTX.rsrc.hqx new file mode 100644 index 000000000..590589153 --- /dev/null +++ b/Mac/TTX.rsrc.hqx @@ -0,0 +1,52 @@ +(This file must be converted with BinHex 4.0) + +:#&48@#jbFh*M!(*cFQ058d9%!3#3"`a'LId!N!3"!!!!#Z8!!!RP!!!"BB"M!!" +,rRlGJ(i!#%[qI[diB!!!5!!!&)#I!!!iI`!!#&48@#jbFh*MD@iZF(PZG(0ZCe0 +C6@a[CbNJ9h*KF(!##h*cFQ058d9%!3$rN!3!N"+dIbpQ!*!'$%B!!$L&!'*,rr2 +T,!-!!%##!!`iB!!!5!!!J)!G!!JS!!!!3B)!1)!G!"3S!!!!3B)!*)"LLqJi!!! +!N!!$!!#!I3!)JCd!&%J*2df!33!81m-!!$J!!!#3!"d!##`Hrrp!JJ!8J'+,f)" +M!!",rRi*5!!!+#`H!!""JJ!31(i!!%[pE68!!!!39%9B9&)UBfJ!U$!a1$%!N!8 +-"!#3"J%"!3#3"3%!N!3(39"36!#3"3)!m!#3$rm4N!iJrr)5N!f`rrmKN!f`rrr +b%T!-X2rrrb'3$,$rrrrb%KZl%T!)X2q3"#%[rk%K)5%[qL%KX2rrrr)5Vrrb%K) +5rrm5%V$rrrmK)Irrqb%K[rrr)5'`rrrb%K[rrrS5'rrrqK)5X2rr)5%Uq[rr)Er +rrrSK)E$rmK)5'U+[rk,rUUUL%K+`rb'3"ErrrrSKN!@`m4+3"4rrrk)5N!@`!5' +3"5VrqL'3"V!"%T!&'[rl%T!'X!%KN!8[rrSK)5(a)5'`!4+3"Irrra)5%[m5%V! +")5'a)5VkrrqUUb(rm5'`!4)DqK+[SUrrrrm5rrm5X!%K,rq[qb'rrrrl)IrrmE! +"%Krrrl)5[rrrmK,rrrq`!5%[rrSK)5Vrrk%Krrrrm!%5(rqL%K)5rrS5%[q3"!% +K)EXKN!3UZb%Krrrrm!%5N![rrrm!!5'3#rrrm!!"%T!,rrm!!!%KN![rm!!!!VZ +3#rm!N!r`!*!&"!$r!*!Irrm,N"`4!2rrra'3'em!rj!%%C!DA`$rN!84N"PI!2q +3"K'3'&m!rj!(%C!%AepI04'3#$8e04'3"&m!rj!)%4%errrrL4'3"cAJp)N4N!4 +I!2q3"a%4%IhrN!3e%C!&0Grrrq!4N!4I!2q3"K%4%6ArN!9I%C!%ArlrN!34N!4 +I!2q3"4'3"&rrN!@Y%4%4Arq3"Id4N!4I!2q3""'3"BRrrIrrrq!e%9rJrj!&V4' +3"&m!rrrr%C!'VBNeVIrrriN4r[qYJiRpL684N!4I!2rr%C!(1c84Arq3"2lrV68 +4N!PI!2m,%C!+0IlrN!5*04'3#Pm!!!X4N!ZYrrrrV684N!YI!!!,%C!,LIrrrem +4N!aI!!!,%C!+0Ilrrrq*%C!'ra'3"9m!!!X4N!Ner[q3"2ie%C!&rrm4N!4I!!! +,%4%409me%4%4VIqYr[rrriQ$V9m4%Irrra%4%9m!!!X4%4'*p)N40BRrJa'*rj! +'rM84rj!%%4&I!!!,%4%4r[rqVIlrAa%4Arq3"Pm4%Iq3"4&I!!!,%4%erj!&Aa% +4%9rrN!AI04%4rj!'A`!!#a%40Iq3")N4N!3eVIq3")-4%4(rN!F!!!X4%6Aqrrq +*%C!'1rrrriNe%4%4rj!)!!X4%4%eAeme%C!(1i0I0"'3"2q3"`!!#a'3&[q3"J! +!!!X4N"ErN!8!N!3,%C!@rj!%!*!&#a'3&[rrr`#3"K&IN"Err`#3([m!N!N"!)! +!!!$rrrrqi!!!![!!!!,i!!!#r!!!![iF!!,r(J'#rMi$`[`r"m,iI`r#m(mI`Z" +[[i,!$r!#`!IJ!N!(`!*!"i!#3!H!JN!2`-*#(mcL4c[mmNIcr2T(irMq4m(irNH +"m2p$!1$q3!!!r%!!!2K!!!$`3!!!i(rrrm!!!!#!J!!!!2rrrrlrrrrqrrrrr[r +rrrlrrrrqrrrrr[rrrrlrrrrqrrrrr[rrrrlrrrrqrrrrr[rrrrlrrrrqIrrrrRr +rrrjrrrrqIrrrrRrrrrjrrrrqIrrrrRrrrrjrrrrqIrrrrhrrrrjrrrrmIrrrq(r +rrr"rrrrJIrrr`!!!!)!!!!"!rrr!!H!"paRh1HpjbhQ$`B1*Pkfpllh[ZFq!$S! +-rrMrN"[qrrcrq!!!!)$a%C!'%[mKN!BVrr)5N!8ErrmVqL%[m5[rrarr%[rb'rr +a[rm[rr%Vra+UrrqUSK[a)5(rqL%K+a)5%[rb%[)E%5XUrrUarbX5rrq[rr,rqa( +rqbrrmIrr%[qb%[m5rrm4)C!&rr!5N!Er!#ZlN!A`!!!!!3$r#j!1%Irr%C!0Arr +rra'3$&rrN!340Iq*%4%4Ar34%9rrN!3eArrr%4(qrrm4%9rrrrm4ArrrrcAJrrr +r%4&Irrm4%Df*rj!%VIf*%4&Ira'3"IlrriN4N!9I#a'3"Ilrra%4%Im4%9m,%69 +I%Dhrrrq*V4(rra&I#a(qrrlrArq3"$ArrrpI#a(rrrpI%BRrrpm4rj!%#a(qrem +4%6[rrc84rj!%#a'3#rrrr`!,%C!,rrm!!"&IN![r!*!'"bU3"!!"!*!%*&4d@'S +!!!!"4P*&4J!"!!!!J!!"!)&*3diM!!%!!!#!!!%!N!8+81!!HK)!!"EMB!!!!!T +3i!#lI!!!I2`!N!3+81!!Zh`!!"EMB!!!!%B""N!!!!!&-5i`B6Bj-5i`B6BJ,5" +MEh"jFQPRD(3J-6Nj15"+GA0d)(CKEL"5Eh0cG@dX)%aPG(4PFR*[FLp5Ef*[4Qp +R!!!!,J%'3!!!!!C-9&)[8NBJ35"QFQ9P)%aPG(4PFR*[FLp5Ef*[4QpR)("bEf4 +eBh3!!!%!!!!+j3!!#H8!!!&K"L-QP$$B!!!!(!&5!!a(9EG*!!!!DP"[F(3!!!" +f3Nj%6!!!!)*8G&KU!!!!MNC548B!!3#DD@0X0!!!!,**3diM!!!![QPMFb-!!!$ ++D@0c0!!!!0CTBh-i!!!!iRCPFR-!!3$Z8dPD43!#!3CTBf`i!!!"+LJ"rrm!N!R +Prrm!!!!8!*!&J2rr!!!*&`#3#b3!N!@!rrm!!!!T!*!&JIrr!!!*$!#3"B$rr`! +!!$3!N!@!rrm!!!Bm!*!&J2rr!!!(3!#3"B$rr`!!"i3!N!@!rrm!!!J)!*!&!Ir +r!!!*D3BM*'`!![rr!!!*X`BM*'6rN!3!!!Nr!*!&!Irr!!!*63#3"[rr!!!*@`# +3"B$rr`!!!MJ!N!316hGZCA)JFQ9cEh9bBfA[d3: diff --git a/Mac/TTXMain.py b/Mac/TTXMain.py new file mode 100644 index 000000000..5c0811b4a --- /dev/null +++ b/Mac/TTXMain.py @@ -0,0 +1,325 @@ +"""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:] == ".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 XML 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 + ".xml" + 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 + ".xml") + 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_ +