Write documentation of script.py
[pyff3.git] / lib.py
blob3da22677b7e408a6b0148d9e9652e36ea6760b9e
1 import os
2 import sys
3 from stat import *
5 import fontforge
7 class MyFont:
9 def __init__(self, input_font):
10 self.file = input_font
11 self.root = os.path.splitext(self.file)[0]
12 self.ff = fontforge.open(input_font)
14 def to_codepoints(self):
15 for glyph in self.ff.glyphs():
16 print "{0:x}".format(glyph.unicode)
18 class InterpolateFonts:
20 """Produce fonts using the interpolateFonts method of FontForge.
22 The kern of this class is the interpolate method.
24 FontForge defines an `interpolateFonts' method for its font type. The
25 amount of blending is defined with a `fraction'. From the FontForge
26 documentation:
28 "If you are interpolating from a light font to a bold one, then a medium
29 font might be 50% between the two, an extra-bold font might be 200% and a
30 thin one -100%."
32 http://fontforge.sourceforge.net/elementmenu.html#Interpolate
34 The three different `parameters' correspond to the three types of
35 interpolation that are alluded to in the FontForge documentation.
37 For example, if the `steps' attribute defines a progression of four fonts,
38 and parameter is `x' then the following fonts are made
39 from_font.interpolateFonts(0, to_font)
40 from_font.interpolateFonts(0.25, to_font)
41 from_font.interpolateFonts(0.5, to_font)
42 from_font.interpolateFonts(0.75, to_font)
43 from_font.interpolateFonts(1, to_font)
45 """
47 def __init__(self, from_font, to_font, parameter, steps):
48 """The from_font is the `initial' font.
49 The to_font is the `final' font.
50 The `steps' determine the number of fonts to be generated.
51 `parameter' determines the type of interpolation.
53 """
54 self.from_font = from_font
55 self.to_font = to_font
56 self.parameter = parameter
57 self.steps = steps
59 def font_info(self):
60 """Define strings for file and font names based on the input fonts."""
61 self.directory = os.path.split(self.from_font)[1] + os.path.split(self.to_font)[1] + self.parameter.upper()
62 self.fromfont_noextension = os.path.splitext(os.path.split(self.from_font)[1])[0]
63 self.tofont_noextension = os.path.splitext(os.path.split(self.to_font)[1])[0]
64 self.filename = self.fromfont_noextension + " to " + self.tofont_noextension + " " + self.parameter.upper()
65 self.familyname = self.fullname = self.fromfont_noextension + " to " + self.tofont_noextension
66 self.fontname = self.fromfont_noextension + "to" + self.tofont_noextension + "-" + self.parameter.upper()
67 self.copyright = "put together by " + sys.argv[0] + " from " + os.path.split(self.from_font)[1] + " and " + os.path.split(self.to_font)[1]
69 def interpolate(self):
70 """Produce a series of fonts using the interpolateFonts method.
72 The fonts are created in a directory whose name is defined in the
73 font_info method. Likewise for the file names, family names, etc.
75 The try/except checks whether the target directory exists already.
77 The number of iterations in the main loop is dependent on the `steps'
78 attribute.
80 """
81 try:
82 os.mkdir(self.directory)
83 except OSError:
84 pass
86 self.from_font_ff = fontforge.open(self.from_font)
88 myfraction = 1.0 / self.steps
90 os.chdir(self.directory)
92 for mystep in range(self.steps):
94 if self.parameter == "x":
95 myfont = self.from_font_ff.interpolateFonts(myfraction * mystep, self.to_font)
96 elif self.parameter == "y":
97 myfont = self.from_font_ff.interpolateFonts(-1 * myfraction * mystep, self.to_font)
98 elif self.parameter == "z":
99 myfont = self.from_font_ff.interpolateFonts(1 + myfraction * mystep, self.to_font)
101 myfont.familyname = self.familyname
102 myfont.fontname = self.fontname + str(int(myfraction * mystep * self.steps)).zfill(5)
103 myfont.fullname = self.fullname + str(int(myfraction * mystep * self.steps)).zfill(5)
104 myfont.copyright = self.copyright
105 myfont.generate(self.filename + str(int(myfraction * mystep * self.steps)).zfill(5) + ".ttf")
107 if self.parameter == "x":
108 myfont = self.from_font_ff.interpolateFonts(1, self.to_font)
109 elif self.parameter == "y":
110 myfont = self.from_font_ff.interpolateFonts(-1, self.to_font)
111 elif self.parameter == "z":
112 myfont = self.from_font_ff.interpolateFonts(2, self.to_font)
114 myfont.familyname = self.familyname
115 myfont.fontname = self.fontname + str(self.steps).zfill(5)
116 myfont.fullname = self.fullname + str(self.steps).zfill(5)
117 myfont.copyright = self.copyright
118 myfont.generate(self.filename + str(self.steps).zfill(5) + ".ttf")
120 os.chdir("..")
122 class InterpolationPathsWrapper:
124 """A font file or a directory of font files may be specified on the cli.
126 This could give rise to permutations.
128 This class is called by the command line script. The two paths are passed
129 directly from the command line to the my_paths tuple and to this class.
131 The extra `parameter' argument determines the type of interpolation as
132 defined in the InterpolateFonts class.
134 We use the stat module to tell files and directories apart
135 http://docs.python.org/library/stat.html
139 def __init__(self, path1, path2, my_parameter, steps):
140 """path1 is the `initial' font or directory of fonts.
141 path1 is the `final' font or directory of fonts.
142 The `steps' determine the number of fonts to be generated.
143 `my_parameter' determines the type of interpolation.
146 self.path1 = path1
147 self.path2 = path2
148 self.my_parameter = my_parameter
149 self.steps = steps
151 def interpolate(self):
152 """Interpolate fonts after the `binary operation' functions."""
153 mode1 = os.stat(self.path1)[ST_MODE]
154 mode2 = os.stat(self.path2)[ST_MODE]
156 if S_ISDIR(mode1) and S_ISDIR(mode2):
157 # Both locations are directories
158 self.directory_times_directory()
159 elif S_ISREG(mode1) and S_ISREG(mode2):
160 # Both locations are files
161 self.font_times_font()
162 elif S_ISREG(mode1):
163 # self.path1 is a file
164 self.font_times_directory()
165 elif S_ISREG(mode2):
166 # self.path2 is a file
167 self.directory_times_font()
169 def font_times_font(self):
170 """Interface to the main method of InterpolateFonts.
172 In turn, this method is an interface to the interpolate method of the
173 fontforge font type.
175 self.path1 and self.path2 are font files on disk.
177 The `binary operations' that follow are in principle based on this
178 function, ie font_times_directory, etc.
181 myfont1_times_myfont2 = InterpolateFonts(self.path1, self.path2, self.my_parameter, self.steps)
182 myfont1_times_myfont2.font_info()
183 myfont1_times_myfont2.interpolate()
185 def font_times_directory(self):
186 """Interpolates self.path1 with all the fonts in self.path2."""
187 for dirpath, dirnames, filenames in os.walk(self.path2):
188 for font2 in filenames:
189 myfont1_times_myfont2 = InterpolateFonts(self.path1, os.path.join(dirpath, font2), self.my_parameter, self.steps)
190 myfont1_times_myfont2.font_info()
191 myfont1_times_myfont2.interpolate()
193 def directory_times_font(self):
194 """Interpolates all the fonts in self.path1 with self.path2."""
195 for dirpath, dirnames, filenames in os.walk(self.path1):
196 for font1 in filenames:
197 myfont1_times_myfont2 = InterpolateFonts(os.path.join(dirpath, font1), self.path2, self.my_parameter, self.steps)
198 myfont1_times_myfont2.font_info()
199 myfont1_times_myfont2.interpolate()
201 def directory_times_directory(self):
202 """Interpolates all the fonts in self.path1 with all the fonts in self.path2."""
203 for dirpath0, dirnames0, filenames0 in os.walk(self.path1):
204 for myfont1 in filenames0:
205 for dirpath1, dirnames1, filenames1 in os.walk(self.path2):
206 for myfont2 in filenames1:
207 myfont1_times_myfont2 = InterpolateFonts(os.path.join(dirpath0, myfont1), os.path.join(dirpath1, myfont2), self.my_parameter, self.steps)
208 myfont1_times_myfont2.font_info()
209 myfont1_times_myfont2.interpolate()