diff options
Diffstat (limited to 'scripts/lib/fontbuild')
-rw-r--r-- | scripts/lib/fontbuild/Build.py | 11 | ||||
-rw-r--r-- | scripts/lib/fontbuild/kerning.py | 102 |
2 files changed, 104 insertions, 9 deletions
diff --git a/scripts/lib/fontbuild/Build.py b/scripts/lib/fontbuild/Build.py index e416ed1..79171bd 100644 --- a/scripts/lib/fontbuild/Build.py +++ b/scripts/lib/fontbuild/Build.py @@ -22,6 +22,7 @@ from fontbuild.convertCurves import glyphCurvesToQuadratic from fontbuild.mitreGlyph import mitreGlyph from fontbuild.generateGlyph import generateGlyph from fontTools.misc.transform import Transform +from fontbuild.kerning import makeKernFeature from fontbuild.features import readFeatureFile, writeFeatureFile from fontbuild.markFeature import GenerateFeature_mark from fontbuild.mkmkFeature import GenerateFeature_mkmk @@ -45,7 +46,6 @@ class FontProject: 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_kerningfeatures = self.basedir + "/" + self.config.get("res","ot_kerningfeaturesdir") adobeGlyphList = open(self.basedir + "/" + self.config.get("res", "agl_glyphlistfile")).readlines() self.adobeGlyphList = dict([line.split(";") for line in adobeGlyphList if not line.startswith("#")]) @@ -171,14 +171,7 @@ class FontProject: if kern: log(">> Generating kern classes") readFeatureFile(f, self.ot_kerningclasses) - weight = f.info.styleName.split()[0] - if weight in ["Light", "Italic"]: - weight = "Regular" - elif weight in ["Medium", "Black"]: - weight = "Bold" - feature_path = os.path.join( - self.ot_kerningfeatures, "Roboto-%s.fea" % weight) - readFeatureFile(f, open(feature_path).read(), prepend=False) + makeKernFeature(f, self.ot_kerningclasses) log(">> Generating font files") GenerateFeature_mark(f) diff --git a/scripts/lib/fontbuild/kerning.py b/scripts/lib/fontbuild/kerning.py new file mode 100644 index 0000000..4e6e47e --- /dev/null +++ b/scripts/lib/fontbuild/kerning.py @@ -0,0 +1,102 @@ +# Copyright 2015 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from feaTools import parser +from feaTools.writers.baseWriter import AbstractFeatureWriter + + +class KernFeatureWriter(AbstractFeatureWriter): + """Generates a kerning feature based on glyph class definitions. + + Uses the kerning rules contained in an RFont's kerning attribute, as well as + glyph classes from parsed OTF text. Class-based rules are set based on the + existing rules for their key glyphs. + """ + + def __init__(self, font): + self.kerning = font.kerning + self.leftClasses = [] + self.rightClasses = [] + + def write(self, linesep="\n"): + """Write kern feature.""" + + # maintain collections of different rule types + leftClassKerning, rightClassKerning, classPairKerning = {}, {}, {} + for leftName, leftContents in self.leftClasses: + leftKey = leftContents[0] + + # collect rules with two classes + for rightName, rightContents in self.rightClasses: + rightKey = rightContents[0] + pair = leftKey, rightKey + if not self.kerning.has_key(pair): + continue + classPairKerning[leftName, rightName] = self.kerning[pair] + self.kerning.remove(pair) + + # collect rules with left class and right glyph + for pair, val in self.kerning.getLeft(leftKey): + if pair == ('O', 'A.smcp'): print pair, val + leftClassKerning[leftName, pair[1]] = self.kerning[pair] + self.kerning.remove(pair) + + # collect rules with left glyph and right class + for rightName, rightContents in self.rightClasses: + rightKey = rightContents[0] + for pair, val in self.kerning.getRight(rightKey): + rightClassKerning[pair[0], rightName] = self.kerning[pair] + self.kerning.remove(pair) + + # write the feature + lines = ["feature kern {"] + lines.append(self._writeKerning(self.kerning, linesep)) + lines.append(self._writeKerning(leftClassKerning, linesep, True)) + lines.append(" subtable;") + lines.append(self._writeKerning(rightClassKerning, linesep, True)) + lines.append(" subtable;") + lines.append(self._writeKerning(classPairKerning, linesep)) + lines.append("} kern;") + return linesep.join(lines) + + def _writeKerning(self, kerning, linesep, enum=""): + """Write kerning rules for a mapping of pairs to values.""" + + lines = [] + enum = "enum " if enum else "" + pairs = kerning.items() + pairs.sort() + for (left, right), val in pairs: + lines.append(" %spos %s %s %d;" % (enum, left, right, val)) + return linesep.join(lines) + + def classDefinition(self, name, contents): + """Store a class definition as either a left- or right-hand class.""" + + if not name.startswith("@_"): + return + info = (name, contents) + if name.endswith("_L"): + self.leftClasses.append(info) + elif name.endswith("_R"): + self.rightClasses.append(info) + + +def makeKernFeature(font, text): + """Add a kern feature to the font, using a KernFeatureWriter.""" + + writer = KernFeatureWriter(font) + parser.parseFeatures(writer, text) + font.features.text += writer.write() |