From f0446ecc7eee2fe55e4f81563e035f8bee01b748 Mon Sep 17 00:00:00 2001 From: James Godfrey-Kittle Date: Wed, 17 Jun 2015 11:25:49 -0700 Subject: Script updates from Paratype 15/06/16. --- scripts/lib/fontbuild/Build.py | 19 ++++++-- scripts/lib/fontbuild/anchors.py | 36 ++++++++++++++ scripts/lib/fontbuild/generateGlyph.py | 87 +++++++++++++++++++++++++++++++++- scripts/lib/fontbuild/instanceNames.py | 27 +++++++---- scripts/lib/fontbuild/italics.py | 11 +++-- scripts/lib/fontbuild/markFeature.py | 73 +++++++++++++++++----------- scripts/lib/fontbuild/mix.py | 4 ++ scripts/lib/fontbuild/mkmkFeature.py | 16 +++++-- 8 files changed, 224 insertions(+), 49 deletions(-) (limited to 'scripts/lib') diff --git a/scripts/lib/fontbuild/Build.py b/scripts/lib/fontbuild/Build.py index 6afc08f..2a7e670 100644 --- a/scripts/lib/fontbuild/Build.py +++ b/scripts/lib/fontbuild/Build.py @@ -28,13 +28,14 @@ class FontProject: self.diacriticList = [line.strip() for line in diacriticList if not line.startswith("#")] self.ot_classes = open(self.basedir + "/" + self.config.get("res","ot_classesfile")).read() self.ot_kerningclasses = open(self.basedir + "/" + self.config.get("res","ot_kerningclassesfile")).read() - self.ot_features = open(self.basedir + "/" + self.config.get("res","ot_featuresfile")).read() + #self.ot_features = open(self.basedir + "/" + self.config.get("res","ot_featuresfile")).read() self.builddir = "out" self.decompose = self.config.get("glyphs","decompose").split() self.predecompose = self.config.get("glyphs","predecompose").split() self.lessItalic = self.config.get("glyphs","lessitalic").split() self.deleteList = self.config.get("glyphs","delete").split() + self.noItalic = self.config.get("glyphs","noitalic").split() self.buildnumber = self.loadBuildNumber() self.buldVFBandFEA = False @@ -82,6 +83,7 @@ class FontProject: narrowAmmount = .96 i = 0 for g in f.glyphs: + i += 1 if i % 10 == 0: print g.name @@ -104,14 +106,21 @@ class FontProject: g.RemoveOverlap() # not sure why FontLab sometimes refuses, seems to work if called twice - + + if (g.name in self.lessItalic): italicizeGlyph(g, 9, stemWidth=stemWidth) - elif g.name != ".notdef": + elif False == (g.name in self.noItalic): italicizeGlyph(g, 10, stemWidth=stemWidth) + #elif g.name != ".notdef": + # italicizeGlyph(g, 10, stemWidth=stemWidth) + g.RemoveOverlap() - g.width += 10 - fl.UpdateGlyph(i-1) + + if g.width != 0: + g.width += 10 + + fl.UpdateGlyph(i-1) if swapSuffixes != None: for swap in swapSuffixes: diff --git a/scripts/lib/fontbuild/anchors.py b/scripts/lib/fontbuild/anchors.py index 7cc3869..08d2d41 100644 --- a/scripts/lib/fontbuild/anchors.py +++ b/scripts/lib/fontbuild/anchors.py @@ -20,6 +20,40 @@ def getAnchorByName(g,anchorName): if a.name == anchorName: return a +def moveMarkAnchors(f, g, anchorName, accentName, dx, dy): + if "top"==anchorName: + anchors = f[accentName].anchors + for anchor in anchors: + if "mkmktop_acc" == anchor.name: + for i in range(len(g.anchors)): + if g.anchors[i].name == "top": + del g.anchors[i] + break + anchor2 = Anchor() + #print anchor.x, dx, anchor.y, dy + anchor2.name = "top" + anchor2.x = anchor.x + int(dx) + anchor2.y = anchor.y + int(dy) + g.anchors.append(anchor2) + + elif anchorName in ["bottom", "bottomu"]: + anchors = f[accentName].anchors + for anchor in anchors: + if "mkmkbottom_acc" == anchor.name: + for n in range(len(g.anchors)): + if g.anchors[n].name == "bottom": + del g.anchors[n] + break + anchor2 = Anchor() + #print anchor.x, dx, anchor.y, dy + anchor2.name = "bottom" + anchor2.x = anchor.x + int(dx) + anchor2.y = anchor.y + int(dy) + for anc in anchors: + if "top" == anc.name: + anchor2.x = anc.x + int(dx) + g.anchors.append(anchor2) + def alignComponentToAnchor(f,glyphName,baseName,accentName,anchorName): g = getGlyph(glyphName,f) @@ -35,6 +69,8 @@ def alignComponentToAnchor(f,glyphName,baseName,accentName,anchorName): c = getComponentByName(f,g,accentName) c.deltas[0].x = offset.x c.deltas[0].y = offset.y + moveMarkAnchors(f, g, anchorName, accentName, offset.x, offset.y) + def alignComponentsToAnchors(f,glyphName,baseName,accentNames): for a in accentNames: diff --git a/scripts/lib/fontbuild/generateGlyph.py b/scripts/lib/fontbuild/generateGlyph.py index f2214f0..7bb8ca2 100644 --- a/scripts/lib/fontbuild/generateGlyph.py +++ b/scripts/lib/fontbuild/generateGlyph.py @@ -1,5 +1,6 @@ from anchors import alignComponentsToAnchors from FL import * +from string import find def parseComposite(composite): c = composite.split("=") @@ -20,6 +21,87 @@ def shiftGlyphMembers(g, x): for c in g.components: c.deltas[0].x = c.deltas[0].x + x +def copyMarkAnchors(f, g, srcname, width): + unicode_range = range(0x0030, 0x02B0) + range(0x1E00, 0x1EFF) + anchors = f[srcname].anchors + for anchor in anchors: + if "top_dd" == anchor.name: + anchor1 = Anchor(anchor) + anchor1.x += width + g.anchors.append(anchor1) + if "bottom_dd" == anchor.name: + anchor1 = Anchor(anchor) + anchor1.x += width + g.anchors.append(anchor1) + if "top0315" == anchor.name: + anchor1 = Anchor(anchor) + anchor1.x += width + g.anchors.append(anchor1) + if "top" == anchor.name: + if g.unicode == None: + if -1 == find(g.name, ".ccmp"): + continue + if False == (g.unicode in unicode_range): + if -1 == find(g.name, ".ccmp"): + continue + #if g.unicode > 0x02B0: + # continue + parenttop_present = 0 + for anc in g.anchors: + if anc.name == "parent_top": + parenttop_present = 1 + if 0 == parenttop_present: + anchor2 = Anchor(anchor) + anchor2.name = "parent_top" +# anchor1.x += width + g.anchors.append(anchor2) + + if "bottom" == anchor.name: + if g.unicode == None: + continue + if False == (g.unicode in unicode_range): + continue + #if g.unicode > 0x02B0: + # continue + bottom_present = 0 + for anc in g.anchors: + if anc.name == "bottom": + bottom_present = 1 + if 0 == bottom_present: + anchor2 = Anchor(anchor) + anchor2.name = "bottom" +# anchor1.x += width + g.anchors.append(anchor2) + + +# anchor1 = Anchor(anchor) +# anchor1.name = "top" +# anchor1.x += width +# g.anchors.append(anchor1) + + # if "rhotichook" == anchor.name: + # anchor1 = Anchor(anchor) + # anchor1.x += width + # g.anchors.append(anchor1) + + #print g.anchors + for anchor in g.anchors: + if "top" == anchor.name: + #print g.name, g.anchors + return + + anchor_parent_top = None + + for anchor in g.anchors: + if "parent_top" == anchor.name: + anchor_parent_top = anchor + break + + if anchor_parent_top: + anchor_top = Anchor(anchor_parent_top) + anchor_top.name = "top" + g.anchors.append(anchor_top) + def generateGlyph(f,gname): if gname.find("_") != -1: generateString = gname @@ -34,14 +116,15 @@ def generateGlyph(f,gname): components.append("NONE") generateString = "%s=%s" %("+".join(components), glyphName) g = f.GenerateGlyph(generateString) + copyMarkAnchors(f, g, baseName, offset[1] + offset[0]) if f.FindGlyph(g.name) == -1: f.glyphs.append(g) g1 = f.glyphs[f.FindGlyph(g.name)] - if len(accentNames) > 0: - alignComponentsToAnchors(f,glyphName,baseName,accentNames) if (offset[0] != 0 or offset[1] != 0): g1.width += offset[1] + offset[0] shiftGlyphMembers(g1,offset[0]) + if len(accentNames) > 0: + alignComponentsToAnchors(f,glyphName,baseName,accentNames) return g # generateGlyph(fl.font,"A+ogonek=Aogonek") diff --git a/scripts/lib/fontbuild/instanceNames.py b/scripts/lib/fontbuild/instanceNames.py index 96827c8..7aa4daa 100644 --- a/scripts/lib/fontbuild/instanceNames.py +++ b/scripts/lib/fontbuild/instanceNames.py @@ -17,7 +17,7 @@ class InstanceNames: def __init__(self,names): if type(names) == type(" "): names = names.split("/") - + #print names self.longfamily = names[0] self.longstyle = names[1] self.shortstyle = names[2] @@ -82,21 +82,29 @@ class InstanceNames: flFont.weight = self.weight flFont.weight_code = self._getWeightCode(self.weight) flFont.width = self.width + if len(self.italic): + flFont.italic_angle = -12 fn = flFont.fontnames fn.clean() - fn.append(NameRecord(0,1,0,0, "Font data copyright %s %s" %(self.foundry, self.year) )) - fn.append(NameRecord(0,3,1,1033, "Font data copyright %s %s" %(self.foundry, self.year) )) + #fn.append(NameRecord(0,1,0,0, "Font data copyright %s %s" %(self.foundry, self.year) )) + #fn.append(NameRecord(0,3,1,1033, "Font data copyright %s %s" %(self.foundry, self.year) )) + fn.append(NameRecord(0,1,0,0, "Copyright %s %s Inc. All Rights Reserved." %(self.year, self.foundry) )) + fn.append(NameRecord(0,3,1,1033, "Copyright %s %s Inc. All Rights Reserved." %(self.year, self.foundry) )) fn.append(NameRecord(1,1,0,0, self.longfamily )) fn.append(NameRecord(1,3,1,1033, self.shortfamily )) fn.append(NameRecord(2,1,0,0, self.longstyle )) fn.append(NameRecord(2,3,1,1033, self.longstyle )) - fn.append(NameRecord(3,1,0,0, "%s:%s:%s" %(self.foundry, self.longfamily, self.year) )) - fn.append(NameRecord(3,3,1,1033, "%s:%s:%s" %(self.foundry, self.longfamily, self.year) )) + #fn.append(NameRecord(3,1,0,0, "%s:%s:%s" %(self.foundry, self.longfamily, self.year) )) + #fn.append(NameRecord(3,3,1,1033, "%s:%s:%s" %(self.foundry, self.longfamily, self.year) )) + fn.append(NameRecord(3,1,0,0, "%s:%s:%s" %(self.foundry, self.fullname, self.year) )) + fn.append(NameRecord(3,3,1,1033, "%s:%s:%s" %(self.foundry, self.fullname, self.year) )) fn.append(NameRecord(4,1,0,0, self.fullname )) fn.append(NameRecord(4,3,1,1033, self.fullname )) - fn.append(NameRecord(5,1,0,0, "Version %s%s; %s" %(self.version, self.build, self.year) )) - fn.append(NameRecord(5,3,1,1033, "Version %s%s; %s" %(self.version, self.build, self.year) )) + #fn.append(NameRecord(5,1,0,0, "Version %s%s; %s" %(self.version, self.build, self.year) )) + #fn.append(NameRecord(5,3,1,1033, "Version %s%s; %s" %(self.version, self.build, self.year) )) + fn.append(NameRecord(5,1,0,0, "Version %s; %s" %(self.version, self.year) )) + fn.append(NameRecord(5,3,1,1033, "Version %s; %s" %(self.version, self.year) )) fn.append(NameRecord(6,1,0,0, self.postscript )) fn.append(NameRecord(6,3,1,1033, self.postscript )) fn.append(NameRecord(7,1,0,0, "%s is a trademark of %s." %(self.longfamily, self.foundry) )) @@ -129,7 +137,7 @@ class InstanceNames: return self._getSubstyle(r"Italic|Oblique|Obliq") def _getWeight(self): - w = self._getSubstyle(r"Extrabold|Superbold|Super|Fat|Bold|Semibold|Demibold|Medium|Light|Thin") + w = self._getSubstyle(r"Extrabold|Superbold|Super|Fat|Black|Bold|Semibold|Demibold|Medium|Light|Thin") if w == "": w = "Regular" return w @@ -141,6 +149,7 @@ class InstanceNames: return w def _getStyleCode(self): + #print "shortstyle:", self.shortstyle styleCode = 0 if self.shortstyle == "Bold": styleCode = 32 @@ -164,7 +173,7 @@ class InstanceNames: elif weight == "Semibold": return 600 elif weight == "Black": - return 800 + return 900 elif weight == "Fat": return 900 diff --git a/scripts/lib/fontbuild/italics.py b/scripts/lib/fontbuild/italics.py index 8e12619..1a42808 100644 --- a/scripts/lib/fontbuild/italics.py +++ b/scripts/lib/fontbuild/italics.py @@ -7,8 +7,11 @@ import math from alignpoints import alignCorners def italicizeGlyph(g, angle=10, stemWidth=185): + unic = g.unicode #save unicode + f = CurrentFont() glyph = f[g.name] + slope = np.tanh([math.pi * angle / 180]) # determine how far on the x axis the glyph should slide @@ -21,10 +24,12 @@ def italicizeGlyph(g, angle=10, stemWidth=185): if len(glyph) > 0: g2 = italicize(f[g.name], angle, xoffset=xoffset, stemWidth=stemWidth) - f.insertGlyph(g2, g.name) - - transformFLGlyphMembers(f[g.name], m) + f.insertGlyph(g2, g.name) + transformFLGlyphMembers(f[g.name], m) + + if unic > 0xFFFF: #restore unicode + g.unicode = unic def italicize(glyph, angle=12, stemWidth=180, xoffset=-50): CURVE_CORRECTION_WEIGHT = .03 diff --git a/scripts/lib/fontbuild/markFeature.py b/scripts/lib/fontbuild/markFeature.py index 9d7401a..b4a8061 100755 --- a/scripts/lib/fontbuild/markFeature.py +++ b/scripts/lib/fontbuild/markFeature.py @@ -8,9 +8,12 @@ def GetAliaseName(gname): return aliases[i][0] return None -def CreateAccNameList(font, acc_anchor_name): +def CreateAccNameList(font, acc_anchor_name, bCombAccentOnly = True): + #combrange = range(0x0300,0x0370) + range(0x1AB0,0x1ABF) + range(0x1DC0,0x1DE0) lst = [] for g in font.glyphs: + if bCombAccentOnly and g.width != 0: #((g.unicode < 0x0300) or (g.unicode > 0x362)): + continue for anchor in g.anchors: if acc_anchor_name == anchor.name: lst.append(g.name) @@ -35,21 +38,23 @@ def CreateGlyphList(font, acc_list, anchor_name): for anchor in g.anchors: if anchor_name == anchor.name: g_list.append([g.name, anchor.x, anchor.y]) - break + break return g_list -def Create_mark_lookup(accent_g_list, base_g_list, lookupname, acc_class): +def Create_mark_lookup(accent_g_list, base_g_list, lookupname, acc_class, lookAliases = True): txt = "lookup " + lookupname + " {\n" for acc in accent_g_list: txt += " markClass " + acc[0] + " " + acc_class +";\n" + for base in base_g_list: txt += " pos base " + base[0] + " mark " + acc_class + ";\n" - base2 = GetAliaseName(base[0]) - if (None == base2): - continue - txt += " pos base " + base2 + " mark " + acc_class + ";\n" + if (lookAliases): + base2 = GetAliaseName(base[0]) + if (None == base2): + continue + txt += " pos base " + base2 + " mark " + acc_class + ";\n" txt += "} " + lookupname + ";\n" @@ -57,28 +62,40 @@ def Create_mark_lookup(accent_g_list, base_g_list, lookupname, acc_class): ##### main ############## def GenerateFeature_mark(font): - text = "feature mark {\n" - accent_name_list = [] - accent_mark_list = [] - base_mark_list = [] - anchor_name = "top" - acc_anchor_name = "_mark" + anchor_name - accent_name_list = CreateAccNameList(font, acc_anchor_name) - accent_mark_list = CreateAccGlyphList(font, accent_name_list, acc_anchor_name) - base_mark_list = CreateGlyphList(font, accent_name_list, anchor_name) - text += Create_mark_lookup(accent_mark_list, base_mark_list, "mark1", "@MC_top") - - accent_name_list = [] - accent_mark_list = [] - base_mark_list = [] - anchor_name = "bottom" - acc_anchor_name = "_mark" + anchor_name - accent_name_list = CreateAccNameList(font, acc_anchor_name) - accent_mark_list = CreateAccGlyphList(font, accent_name_list, acc_anchor_name) - base_mark_list = CreateGlyphList(font, accent_name_list, anchor_name) - text += Create_mark_lookup(accent_mark_list, base_mark_list, "mark2", "@MC_bottom") + combination_anchor_list = [ + ["top", "_marktop", True, True], + ["bottom", "_markbottom", True, True], + ["top_dd", "_marktop_dd", True, False], + ["bottom_dd", "_markbottom_dd", True, False], + ["rhotichook", "_markrhotichook", False, False], + ["top0315", "_marktop0315", False, False], + ["parent_top", "_markparent_top", False, False], + ["parenthesses.w1", "_markparenthesses.w1", False, False], + ["parenthesses.w2", "_markparenthesses.w2", False, False], + ["parenthesses.w3", "_markparenthesses.w3", False, False] + ] + + text = "feature mark {\n" + + for n in range(len(combination_anchor_list)): + + accent_name_list = [] + accent_mark_list = [] + base_mark_list = [] + + anchors_pair = combination_anchor_list[n] + anchor_name = anchors_pair[0] + acc_anchor_name = anchors_pair[1] + comb_accent_only = anchors_pair[2] + expand_to_composits = anchors_pair[3] + lookupname = "mark"+`n+1` + classname = "@MC_" + anchor_name + accent_name_list = CreateAccNameList(font, acc_anchor_name, comb_accent_only) + accent_mark_list = CreateAccGlyphList(font, accent_name_list, acc_anchor_name) + base_mark_list = CreateGlyphList(font, accent_name_list, anchor_name) + text += Create_mark_lookup(accent_mark_list, base_mark_list, lookupname, classname, expand_to_composits) text += "} mark;\n" mark = Feature("mark", text) @@ -91,3 +108,5 @@ def GenerateFeature_mark(font): if (not_exist): font.features.append(mark) + + diff --git a/scripts/lib/fontbuild/mix.py b/scripts/lib/fontbuild/mix.py index 06c62dc..c55512a 100644 --- a/scripts/lib/fontbuild/mix.py +++ b/scripts/lib/fontbuild/mix.py @@ -46,6 +46,7 @@ class FFont: def addDiff(self,b,c): newFont = FFont(self) + for key,g in newFont.glyphs.iteritems(): gB = b.getGlyph(key) gC = c.getGlyph(key) @@ -53,6 +54,7 @@ class FFont: newFont.glyphs[key] = g.addDiff(gB,gC) except: print "Add diff failed for '%s'" %key + return newFont class FGlyph: @@ -250,6 +252,8 @@ class Master: kernlist = [KerningPair(k) for k in oldGlyph.kerning] font.glyphs[glyphIndex] = Glyph(overlayGlyph) font.glyphs[glyphIndex].kerning = kernlist + if 0 == overlayGlyph: + font.glyphs[glyphIndex].width = 0 else: font.glyphs.append(overlayGlyph) fl.UpdateFont(ifont) diff --git a/scripts/lib/fontbuild/mkmkFeature.py b/scripts/lib/fontbuild/mkmkFeature.py index b7281c6..fd2a968 100755 --- a/scripts/lib/fontbuild/mkmkFeature.py +++ b/scripts/lib/fontbuild/mkmkFeature.py @@ -28,9 +28,9 @@ def CreateGlyphList(font, acc_list, anchor_name): break return g_list -def Create_mkmk1(accent_g_list, base_g_list, lookupname): +def Create_mkmk1(accent_g_list, base_g_list, lookupname, acc_class): txt = "lookup " + lookupname + " {\n" - acc_class = "@MC_mkmk" + #acc_class = "@MC_mkmk" for acc in accent_g_list: txt += " markClass " + acc[0] + " " + acc_class +";\n" @@ -54,7 +54,17 @@ def GenerateFeature_mkmk(font): accent_name_list = CreateAccNameList(font, acc_anchor_name) accent_mark_list = CreateAccGlyphList(font, accent_name_list, acc_anchor_name) base_mark_list = CreateGlyphList(font, accent_name_list, anchor_name) - text += Create_mkmk1(accent_mark_list, base_mark_list, "mkmk1") + text += Create_mkmk1(accent_mark_list, base_mark_list, "mkmk1", "@MC_mkmk_top") + + accent_name_list = [] + accent_mark_list = [] + base_mark_list = [] + anchor_name = "mkmkbottom_acc" + acc_anchor_name = "_markbottom" + accent_name_list = CreateAccNameList(font, acc_anchor_name) + accent_mark_list = CreateAccGlyphList(font, accent_name_list, acc_anchor_name) + base_mark_list = CreateGlyphList(font, accent_name_list, anchor_name) + text += Create_mkmk1(accent_mark_list, base_mark_list, "mkmk2", "@MC_mkmk_bottom") text += "} mkmk;\n" mkmk = Feature("mkmk", text) -- cgit v1.2.3