summaryrefslogtreecommitdiff
path: root/scripts/lib/fontbuild
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/fontbuild')
-rw-r--r--scripts/lib/fontbuild/Build.py11
-rw-r--r--scripts/lib/fontbuild/kerning.py102
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()