diff options
Diffstat (limited to 'misc/pylib/fontbuild/features.py')
-rwxr-xr-x | misc/pylib/fontbuild/features.py | 189 |
1 files changed, 0 insertions, 189 deletions
diff --git a/misc/pylib/fontbuild/features.py b/misc/pylib/fontbuild/features.py deleted file mode 100755 index fe6eca012..000000000 --- a/misc/pylib/fontbuild/features.py +++ /dev/null @@ -1,189 +0,0 @@ -# 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. - - -import re - -from feaTools import parser -from feaTools.writers.fdkSyntaxWriter import FDKSyntaxFeatureWriter - - -class FilterFeatureWriter(FDKSyntaxFeatureWriter): - """Feature writer to detect invalid references and duplicate definitions.""" - - def __init__(self, refs=set(), name=None, isFeature=False): - """Initializes the set of known references, empty by default.""" - self.refs = refs - self.featureNames = set() - self.lookupNames = set() - self.tableNames = set() - self.languageSystems = set() - super(FilterFeatureWriter, self).__init__( - name=name, isFeature=isFeature) - - # error to print when undefined reference is found in glyph class - self.classErr = ('Undefined reference "%s" removed from glyph class ' - 'definition %s.') - - # error to print when undefined reference is found in sub or pos rule - subErr = ['Substitution rule with undefined reference "%s" removed'] - if self._name: - subErr.append(" from ") - subErr.append("feature" if self._isFeature else "lookup") - subErr.append(' "%s"' % self._name) - subErr.append(".") - self.subErr = "".join(subErr) - self.posErr = self.subErr.replace("Substitution", "Positioning") - - def _subwriter(self, name, isFeature): - """Use this class for nested expressions e.g. in feature definitions.""" - return FilterFeatureWriter(self.refs, name, isFeature) - - def _flattenRefs(self, refs, flatRefs): - """Flatten a list of references.""" - for ref in refs: - if type(ref) == list: - self._flattenRefs(ref, flatRefs) - elif ref != "'": # ignore contextual class markings - flatRefs.append(ref) - - def _checkRefs(self, refs, errorMsg): - """Check a list of references found in a sub or pos rule.""" - flatRefs = [] - self._flattenRefs(refs, flatRefs) - for ref in flatRefs: - # trailing apostrophes should be ignored - if ref[-1] == "'": - ref = ref[:-1] - if ref not in self.refs: - print errorMsg % ref - # insert an empty instruction so that we can't end up with an - # empty block, which is illegal syntax - super(FilterFeatureWriter, self).rawText(";") - return False - return True - - def classDefinition(self, name, contents): - """Check that contents are valid, then add name to known references.""" - if name in self.refs: - return - newContents = [] - for ref in contents: - if ref not in self.refs and ref != "-": - print self.classErr % (ref, name) - else: - newContents.append(ref) - self.refs.add(name) - super(FilterFeatureWriter, self).classDefinition(name, newContents) - - def gsubType1(self, target, replacement): - """Check a sub rule with one-to-one replacement.""" - if self._checkRefs([target, replacement], self.subErr): - super(FilterFeatureWriter, self).gsubType1(target, replacement) - - def gsubType4(self, target, replacement): - """Check a sub rule with many-to-one replacement.""" - if self._checkRefs([target, replacement], self.subErr): - super(FilterFeatureWriter, self).gsubType4(target, replacement) - - def gsubType6(self, precedingContext, target, trailingContext, replacement): - """Check a sub rule with contextual replacement.""" - refs = [precedingContext, target, trailingContext, replacement] - if self._checkRefs(refs, self.subErr): - super(FilterFeatureWriter, self).gsubType6( - precedingContext, target, trailingContext, replacement) - - def gposType1(self, target, value): - """Check a single positioning rule.""" - if self._checkRefs([target], self.posErr): - super(FilterFeatureWriter, self).gposType1(target, value) - - def gposType2(self, target, value, needEnum=False): - """Check a pair positioning rule.""" - if self._checkRefs(target, self.posErr): - super(FilterFeatureWriter, self).gposType2(target, value, needEnum) - - # these rules may contain references, but they aren't present in Roboto - def gsubType3(self, target, replacement): - raise NotImplementedError - - def feature(self, name): - """Adds a feature definition only once.""" - if name not in self.featureNames: - self.featureNames.add(name) - return super(FilterFeatureWriter, self).feature(name) - # we must return a new writer even if we don't add it to this one - return FDKSyntaxFeatureWriter(name, True) - - def lookup(self, name): - """Adds a lookup block only once.""" - if name not in self.lookupNames: - self.lookupNames.add(name) - return super(FilterFeatureWriter, self).lookup(name) - # we must return a new writer even if we don't add it to this one - return FDKSyntaxFeatureWriter(name, False) - - def languageSystem(self, langTag, scriptTag): - """Adds a language system instruction only once.""" - system = (langTag, scriptTag) - if system not in self.languageSystems: - self.languageSystems.add(system) - super(FilterFeatureWriter, self).languageSystem(langTag, scriptTag) - - def table(self, name, data): - """Adds a table only once.""" - if name in self.tableNames: - return - self.tableNames.add(name) - self._instructions.append("table %s {" % name) - self._instructions.extend([" %s %s;" % line for line in data]) - self._instructions.append("} %s;" % name) - - -def compileFeatureRE(name): - """Compiles a feature-matching regex.""" - - # this is the pattern used internally by feaTools: - # https://github.com/typesupply/feaTools/blob/master/Lib/feaTools/parser.py - featureRE = list(parser.featureContentRE) - featureRE.insert(2, name) - featureRE.insert(6, name) - return re.compile("".join(featureRE)) - - -def updateFeature(font, name, value): - """Add a feature definition, or replace existing one.""" - featureRE = compileFeatureRE(name) - if featureRE.search(font.features.text): - font.features.text = featureRE.sub(value, font.features.text) - else: - font.features.text += "\n" + value - - -def readFeatureFile(font, text, prepend=True): - """Incorporate valid definitions from feature text into font.""" - writer = FilterFeatureWriter(set(font.keys())) - if prepend: - text += font.features.text - else: - text = font.features.text + text - parser.parseFeatures(writer, text) - font.features.text = writer.write() - - -def writeFeatureFile(font, path): - """Write the font's features to an external file.""" - fout = open(path, "w") - fout.write(font.features.text) - fout.close() |