2015-08-01 14:49:19 +02:00
|
|
|
from __future__ import print_function, division, absolute_import
|
|
|
|
from __future__ import unicode_literals
|
2015-09-07 16:10:13 +02:00
|
|
|
import itertools
|
2015-08-01 14:49:19 +02:00
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class Statement(object):
|
|
|
|
def __init__(self, location):
|
|
|
|
self.location = location
|
2015-08-01 14:49:19 +02:00
|
|
|
|
2015-09-04 15:06:11 +02:00
|
|
|
def build(self, builder):
|
|
|
|
pass
|
|
|
|
|
2015-08-01 14:49:19 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class Block(Statement):
|
|
|
|
def __init__(self, location):
|
|
|
|
Statement.__init__(self, location)
|
|
|
|
self.statements = []
|
|
|
|
|
|
|
|
def build(self, builder):
|
|
|
|
for s in self.statements:
|
|
|
|
s.build(builder)
|
|
|
|
|
|
|
|
|
|
|
|
class FeatureFile(Block):
|
|
|
|
def __init__(self):
|
|
|
|
Block.__init__(self, location=None)
|
|
|
|
|
|
|
|
|
|
|
|
class FeatureBlock(Block):
|
2015-08-11 15:28:59 +02:00
|
|
|
def __init__(self, location, name, use_extension):
|
2015-09-04 16:11:53 +02:00
|
|
|
Block.__init__(self, location)
|
2015-08-11 15:28:59 +02:00
|
|
|
self.name, self.use_extension = name, use_extension
|
2015-08-01 19:58:54 +02:00
|
|
|
|
2015-09-04 22:29:06 +02:00
|
|
|
def build(self, builder):
|
|
|
|
# TODO(sascha): Handle use_extension.
|
|
|
|
builder.start_feature(self.location, self.name)
|
|
|
|
Block.build(self, builder)
|
2015-09-07 11:14:03 +02:00
|
|
|
builder.end_feature()
|
2015-09-04 22:29:06 +02:00
|
|
|
|
2015-08-01 19:58:54 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class LookupBlock(Block):
|
2015-08-11 10:59:26 +02:00
|
|
|
def __init__(self, location, name, use_extension):
|
2015-09-04 16:11:53 +02:00
|
|
|
Block.__init__(self, location)
|
2015-08-11 10:59:26 +02:00
|
|
|
self.name, self.use_extension = name, use_extension
|
|
|
|
|
2015-09-07 13:33:44 +02:00
|
|
|
def build(self, builder):
|
|
|
|
# TODO(sascha): Handle use_extension.
|
|
|
|
builder.start_lookup_block(self.location, self.name)
|
|
|
|
Block.build(self, builder)
|
|
|
|
builder.end_lookup_block()
|
|
|
|
|
2015-08-11 10:59:26 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class GlyphClassDefinition(Statement):
|
2015-08-01 17:34:02 +02:00
|
|
|
def __init__(self, location, name, glyphs):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-01 17:34:02 +02:00
|
|
|
self.name = name
|
|
|
|
self.glyphs = glyphs
|
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class AlternateSubstitution(Statement):
|
2015-08-11 15:54:54 +02:00
|
|
|
def __init__(self, location, glyph, from_class):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-11 15:54:54 +02:00
|
|
|
self.glyph, self.from_class = (glyph, from_class)
|
|
|
|
|
2015-09-07 11:14:03 +02:00
|
|
|
def build(self, builder):
|
|
|
|
builder.add_alternate_substitution(self.location, self.glyph,
|
|
|
|
self.from_class)
|
|
|
|
|
2015-08-11 15:54:54 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class AnchorDefinition(Statement):
|
2015-08-11 12:53:30 +02:00
|
|
|
def __init__(self, location, name, x, y, contourpoint):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-11 12:53:30 +02:00
|
|
|
self.name, self.x, self.y, self.contourpoint = name, x, y, contourpoint
|
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class LanguageStatement(Statement):
|
2015-08-10 16:30:10 +02:00
|
|
|
def __init__(self, location, language, include_default, required):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-09-07 21:34:10 +02:00
|
|
|
assert(len(language) == 4)
|
2015-08-10 16:30:10 +02:00
|
|
|
self.language = language
|
|
|
|
self.include_default = include_default
|
|
|
|
self.required = required
|
2015-08-10 11:30:47 +02:00
|
|
|
|
2015-09-04 22:29:06 +02:00
|
|
|
def build(self, builder):
|
|
|
|
builder.set_language(location=self.location, language=self.language,
|
2015-09-08 15:55:54 +02:00
|
|
|
include_default=self.include_default,
|
|
|
|
required=self.required)
|
2015-09-04 22:29:06 +02:00
|
|
|
|
2015-08-10 11:30:47 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class LanguageSystemStatement(Statement):
|
2015-08-01 14:49:19 +02:00
|
|
|
def __init__(self, location, script, language):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-01 14:49:19 +02:00
|
|
|
self.script, self.language = (script, language)
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
def build(self, builder):
|
|
|
|
builder.add_language_system(self.location, self.script, self.language)
|
|
|
|
|
2015-08-04 11:01:04 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class IgnoreSubstitutionRule(Statement):
|
2015-08-05 10:41:04 +02:00
|
|
|
def __init__(self, location, prefix, glyphs, suffix):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-05 10:41:04 +02:00
|
|
|
self.prefix, self.glyphs, self.suffix = (prefix, glyphs, suffix)
|
|
|
|
|
|
|
|
|
2015-09-07 16:10:13 +02:00
|
|
|
class LigatureSubstitution(Statement):
|
|
|
|
def __init__(self, location, glyphs, replacement):
|
|
|
|
Statement.__init__(self, location)
|
|
|
|
self.glyphs, self.replacement = (glyphs, replacement)
|
|
|
|
|
|
|
|
def build(self, builder):
|
|
|
|
# OpenType feature file syntax, section 5.d, "Ligature substitution":
|
|
|
|
# "Since the OpenType specification does not allow ligature
|
|
|
|
# substitutions to be specified on target sequences that contain
|
|
|
|
# glyph classes, the implementation software will enumerate
|
|
|
|
# all specific glyph sequences if glyph classes are detected"
|
|
|
|
for glyphs in sorted(itertools.product(*self.glyphs)):
|
|
|
|
builder.add_ligature_substitution(
|
|
|
|
self.location, glyphs, self.replacement)
|
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class LookupReferenceStatement(Statement):
|
2015-08-11 10:59:26 +02:00
|
|
|
def __init__(self, location, lookup):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-11 10:59:26 +02:00
|
|
|
self.location, self.lookup = (location, lookup)
|
|
|
|
|
2015-09-28 16:49:17 +02:00
|
|
|
def build(self, builder):
|
|
|
|
for s in self.lookup.statements:
|
|
|
|
s.build(builder)
|
|
|
|
|
2015-08-11 10:59:26 +02:00
|
|
|
|
2015-09-08 12:05:44 +02:00
|
|
|
class MultipleSubstitution(Statement):
|
|
|
|
def __init__(self, location, glyph, replacement):
|
|
|
|
Statement.__init__(self, location)
|
|
|
|
self.glyph, self.replacement = glyph, replacement
|
|
|
|
|
|
|
|
def build(self, builder):
|
2015-09-10 15:28:02 +02:00
|
|
|
builder.add_multiple_substitution(self.location,
|
|
|
|
self.glyph, self.replacement)
|
2015-09-08 12:05:44 +02:00
|
|
|
|
|
|
|
|
2015-12-03 13:05:42 +01:00
|
|
|
class ReverseChainingSingleSubstitution(Statement):
|
|
|
|
def __init__(self, location, old_prefix, old_suffix, mapping):
|
|
|
|
Statement.__init__(self, location)
|
|
|
|
self.old_prefix, self.old_suffix = old_prefix, old_suffix
|
|
|
|
self.mapping = mapping
|
|
|
|
|
|
|
|
def build(self, builder):
|
|
|
|
builder.add_reverse_chaining_single_substitution(
|
|
|
|
self.location, self.old_prefix, self.old_suffix, self.mapping)
|
|
|
|
|
|
|
|
|
2015-09-08 10:33:07 +02:00
|
|
|
class SingleSubstitution(Statement):
|
|
|
|
def __init__(self, location, mapping):
|
|
|
|
Statement.__init__(self, location)
|
|
|
|
self.mapping = mapping
|
|
|
|
|
|
|
|
def build(self, builder):
|
|
|
|
builder.add_single_substitution(self.location, self.mapping)
|
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class ScriptStatement(Statement):
|
2015-08-10 16:30:10 +02:00
|
|
|
def __init__(self, location, script):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-10 16:30:10 +02:00
|
|
|
self.script = script
|
|
|
|
|
2015-09-04 22:29:06 +02:00
|
|
|
def build(self, builder):
|
|
|
|
builder.set_script(self.location, self.script)
|
|
|
|
|
2015-08-10 16:30:10 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class SubtableStatement(Statement):
|
2015-08-11 15:14:47 +02:00
|
|
|
def __init__(self, location):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-11 15:14:47 +02:00
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class SubstitutionRule(Statement):
|
2015-08-04 19:55:55 +02:00
|
|
|
def __init__(self, location, old, new):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
|
|
|
self.old, self.new = (old, new)
|
2015-08-04 19:55:55 +02:00
|
|
|
self.old_prefix = []
|
|
|
|
self.old_suffix = []
|
2015-08-11 12:22:07 +02:00
|
|
|
self.lookups = [None] * len(old)
|
2015-08-04 19:55:55 +02:00
|
|
|
|
2015-11-30 15:02:09 +01:00
|
|
|
def build(self, builder):
|
|
|
|
builder.add_substitution(
|
2015-12-03 13:05:42 +01:00
|
|
|
self.location, self.old_prefix, self.old, self.old_suffix,
|
2015-11-30 15:02:09 +01:00
|
|
|
self.new, self.lookups)
|
|
|
|
|
2015-08-04 19:55:55 +02:00
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class ValueRecord(Statement):
|
2015-08-04 11:01:04 +02:00
|
|
|
def __init__(self, location, xPlacement, yPlacement, xAdvance, yAdvance):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-04 11:01:04 +02:00
|
|
|
self.xPlacement, self.yPlacement = (xPlacement, yPlacement)
|
|
|
|
self.xAdvance, self.yAdvance = (xAdvance, yAdvance)
|
|
|
|
|
|
|
|
|
2015-09-04 16:11:53 +02:00
|
|
|
class ValueRecordDefinition(Statement):
|
2015-08-04 11:01:04 +02:00
|
|
|
def __init__(self, location, name, value):
|
2015-09-04 16:11:53 +02:00
|
|
|
Statement.__init__(self, location)
|
2015-08-04 11:01:04 +02:00
|
|
|
self.name = name
|
|
|
|
self.value = value
|