1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
"""Remote control for MacOS FontLab.
initFontLabRemote() registers a callback for appleevents and
runFontLabRemote() sends the code from a different application,
such as a Mac Python IDE or Python interpreter.
"""
from robofab.world import world
if world.inFontLab and world.mac is not None:
from Carbon import AE as _AE
else:
import sys
from aetools import TalkTo
class FontLab(TalkTo):
pass
__all__ = ['initFontLabRemote', 'runFontLabRemote']
def _executePython(theAppleEvent, theReply):
import aetools
import cStringIO
import traceback
import sys
parms, attrs = aetools.unpackevent(theAppleEvent)
source = parms.get("----")
if source is None:
return
stdout = cStringIO.StringIO()
#print "<executing remote command>"
save = sys.stdout, sys.stderr
sys.stdout = sys.stderr = stdout
namespace = {}
try:
try:
exec source in namespace
except:
traceback.print_exc()
finally:
sys.stdout, sys.stderr = save
output = stdout.getvalue()
aetools.packevent(theReply, {"----": output})
_imported = False
def initFontLabRemote():
"""Call this in FontLab at startup of the application to switch on the remote."""
print "FontLabRemote is on."
_AE.AEInstallEventHandler("Rfab", "exec", _executePython)
if world.inFontLab and world.mac is not None:
initFontLabRemote()
def runFontLabRemote(code):
"""Call this in the MacOS Python IDE to make FontLab execute the code."""
fl = FontLab("FLab", start=1)
ae, parms, attrs = fl.send("Rfab", "exec", {"----": code})
output = parms.get("----")
return output
# GlyphTransmit
# Convert a glyph to a string using digestPen, transmit string, unpack string with pointpen.
#
def Glyph2String(glyph):
from robofab.pens.digestPen import DigestPointPen
import pickle
p = DigestPointPen(glyph)
glyph.drawPoints(p)
info = {}
info['name'] = glyph.name
info['width'] = glyph.width
info['points'] = p.getDigest()
return str(pickle.dumps(info))
def String2Glyph(gString, penClass, font):
import pickle
if gString is None:
return None
info = pickle.loads(gString)
name = info['name']
if not name in font.keys():
glyph = font.newGlyph(name)
else:
glyph = font[name]
pen = penClass(glyph)
for p in info['points']:
if p == "beginPath":
pen.beginPath()
elif p == "endPath":
pen.endPath()
else:
pt, type = p
pen.addPoint(pt, type)
glyph.width = info['width']
glyph.update()
return glyph
_makeFLGlyph = """
from robofab.world import CurrentFont
from robofab.tools.remote import receiveGlyph
code = '''%s'''
receiveGlyph(code, CurrentFont())
"""
def transmitGlyph(glyph):
from robofab.world import world
if world.inFontLab and world.mac is not None:
# we're in fontlab, on a mac
print Glyph2String(glyph)
pass
else:
remoteProgram = _makeFLGlyph%Glyph2String(glyph)
print "remoteProgram", remoteProgram
return runFontLabRemote(remoteProgram)
def receiveGlyph(glyphString, font=None):
from robofab.world import world
if world.inFontLab and world.mac is not None:
# we're in fontlab, on a mac
from robofab.pens.flPen import FLPointPen
print String2Glyph(glyphString, FLPointPen, font)
pass
else:
from robofab.pens.rfUFOPen import RFUFOPointPen
print String2Glyph(glyphString, RFUFOPointPen, font)
#
# command to tell FontLab to open a UFO and save it as a vfb
def os9PathConvert(path):
"""Attempt to convert a unix style path to a Mac OS9 style path.
No support for relative paths!
"""
if path.find("/Volumes") == 0:
# it's on the volumes list, some sort of external volume
path = path[len("/Volumes")+1:]
elif path[0] == "/":
# a dir on the root volume
path = path[1:]
new = path.replace("/", ":")
return new
_remoteUFOImportProgram = """
from robofab.objects.objectsFL import NewFont
import os.path
destinationPathVFB = "%(destinationPathVFB)s"
font = NewFont()
font.readUFO("%(sourcePathUFO)s", doProgress=True)
font.update()
font.save(destinationPathVFB)
print font, "done"
font.close()
"""
def makeVFB(sourcePathUFO, destinationPathVFB=None):
"""FontLab convenience function to import a UFO and save it as a VFB"""
import os
fl = FontLab("FLab", start=1)
if destinationPathVFB is None:
destinationPathVFB = os.path.splitext(sourcePathUFO)[0]+".vfb"
src9 = os9PathConvert(sourcePathUFO)
dst9 = os9PathConvert(destinationPathVFB)
code = _remoteUFOImportProgram%{'sourcePathUFO': src9, 'destinationPathVFB':dst9}
ae, parms, attrs = fl.send("Rfab", "exec", {"----": code})
output = parms.get("----")
return output
|