Merge remote-tracking branch 'origin/master' into colrv1-rev2

This commit is contained in:
Cosimo Lupo 2020-07-03 12:58:57 +01:00
commit 64731aedd0
No known key found for this signature in database
GPG Key ID: 179A8F0895A02F4F
8 changed files with 1287 additions and 200 deletions

View File

@ -1,8 +0,0 @@
#######
builder
#######
.. automodule:: fontTools.otlLib.builder
:inherited-members:
:members:
:undoc-members:

View File

@ -1,13 +1,74 @@
######
otlLib
######
#################################################
otlLib: Routines for working with OpenType Layout
#################################################
.. toctree::
:maxdepth: 2
The ``fontTools.otlLib`` library provides routines to help you create the
subtables and other data structures you need when you are editing a font's
``GSUB`` and ``GPOS`` tables: substitution and positioning rules, anchors,
lookups, coverage tables and so on.
builder
------------------------------------------
High-level OpenType Layout Lookup Builders
------------------------------------------
.. automodule:: fontTools.otlLib
:inherited-members:
:members:
:undoc-members:
.. automodule:: fontTools.otlLib.builder
:members: AlternateSubstBuilder, ChainContextPosBuilder, ChainContextSubstBuilder, LigatureSubstBuilder, MultipleSubstBuilder, CursivePosBuilder, MarkBasePosBuilder, MarkLigPosBuilder, MarkMarkPosBuilder, ReverseChainSingleSubstBuilder, SingleSubstBuilder, ClassPairPosSubtableBuilder, PairPosBuilder, SinglePosBuilder
:member-order: bysource
--------------------------------------
Common OpenType Layout Data Structures
--------------------------------------
.. automodule:: fontTools.otlLib.builder
:members: buildCoverage, buildLookup
------------------------------------
Low-level GSUB Table Lookup Builders
------------------------------------
These functions deal with the "simple" lookup types. See above for classes to
help build more complex lookups (contextual and chaining lookups).
.. automodule:: fontTools.otlLib.builder
:members: buildSingleSubstSubtable, buildMultipleSubstSubtable, buildAlternateSubstSubtable, buildLigatureSubstSubtable
--------------------------
GPOS Shared Table Builders
--------------------------
The functions help build the `GPOS shared tables <https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#shared-tables-value-record-anchor-table-and-mark-array-table>`_
as defined in the OpenType spec: value records, anchors, mark arrays and
mark record tables.
.. automodule:: fontTools.otlLib.builder
:members: buildValue, buildAnchor, buildMarkArray, buildDevice, buildBaseArray, buildComponentRecord, buildMarkArray, buildValue
:member-order: bysource
------------------------------------
Low-level GPOS Table Lookup Builders
------------------------------------
These functions deal with the "simple" lookup types. See above for classes to
help build more complex lookups (contextual and chaining lookups).
.. automodule:: fontTools.otlLib.builder
:members: buildCursivePosSubtable, buildLigatureArray, buildMarkBasePos, buildMarkBasePosSubtable, buildMarkLigPos, buildMarkLigPosSubtable, buildPairPosClassesSubtable, buildPairPosGlyphs, buildPairPosGlyphsSubtable, buildSinglePos, buildSinglePosSubtable
:member-order: bysource
----------------------------
GDEF Table Subtable Builders
----------------------------
These functions build subtables for elements of the ``GDEF`` table.
.. automodule:: fontTools.otlLib.builder
:members: buildAttachList, buildLigCaretList, buildMarkGlyphSetsDef
:member-order: bysource
------------------
STAT Table Builder
------------------
.. automodule:: fontTools.otlLib.builder
:members: buildStatTable
:member-order: bysource

View File

@ -868,7 +868,7 @@ class Builder(object):
def add_chain_context_subst(self, location,
prefix, glyphs, suffix, lookups):
lookup = self.get_lookup_(location, ChainContextSubstBuilder)
lookup.substitutions.append((prefix, glyphs, suffix,
lookup.rules.append((prefix, glyphs, suffix,
self.find_lookup_builders_(lookups)))
def add_alternate_subst(self, location,
@ -880,7 +880,7 @@ class Builder(object):
if prefix or suffix:
chain = self.get_lookup_(location, ChainContextSubstBuilder)
lookup = self.get_chained_lookup_(location, AlternateSubstBuilder)
chain.substitutions.append((prefix, [{glyph}], suffix, [lookup]))
chain.rules.append((prefix, [{glyph}], suffix, [lookup]))
else:
lookup = self.get_lookup_(location, AlternateSubstBuilder)
if glyph in lookup.alternates:
@ -935,7 +935,7 @@ class Builder(object):
if prefix or suffix or forceChain:
chain = self.get_lookup_(location, ChainContextSubstBuilder)
lookup = self.get_chained_lookup_(location, LigatureSubstBuilder)
chain.substitutions.append((prefix, glyphs, suffix, [lookup]))
chain.rules.append((prefix, glyphs, suffix, [lookup]))
else:
lookup = self.get_lookup_(location, LigatureSubstBuilder)
@ -953,7 +953,7 @@ class Builder(object):
chain = self.get_lookup_(location, ChainContextSubstBuilder)
sub = self.get_chained_lookup_(location, MultipleSubstBuilder)
sub.mapping[glyph] = replacements
chain.substitutions.append((prefix, [{glyph}], suffix, [sub]))
chain.rules.append((prefix, [{glyph}], suffix, [sub]))
return
lookup = self.get_lookup_(location, MultipleSubstBuilder)
if glyph in lookup.mapping:
@ -973,7 +973,7 @@ class Builder(object):
def add_reverse_chain_single_subst(self, location, old_prefix,
old_suffix, mapping):
lookup = self.get_lookup_(location, ReverseChainSingleSubstBuilder)
lookup.substitutions.append((old_prefix, old_suffix, mapping))
lookup.rules.append((old_prefix, old_suffix, mapping))
def add_single_subst(self, location, prefix, suffix, mapping, forceChain):
if self.cur_feature_name_ == "aalt":
@ -1007,7 +1007,7 @@ class Builder(object):
if sub is None:
sub = self.get_chained_lookup_(location, SingleSubstBuilder)
sub.mapping.update(mapping)
chain.substitutions.append((prefix, [mapping.keys()], suffix, [sub]))
chain.rules.append((prefix, [mapping.keys()], suffix, [sub]))
def add_cursive_pos(self, location, glyphclass, entryAnchor, exitAnchor):
lookup = self.get_lookup_(location, CursivePosBuilder)

File diff suppressed because it is too large Load Diff

View File

@ -452,7 +452,7 @@ class GlyphSet(_UFOBaseIO):
self._existingFileNames = {}
for fileName in self.contents.values():
self._existingFileNames[fileName] = fileName.lower()
fileName = self.glyphNameToFileName(glyphName, self._existingFileNames)
fileName = self.glyphNameToFileName(glyphName, self._existingFileNames.values())
self.contents[glyphName] = fileName
self._existingFileNames[fileName] = fileName.lower()
if self._reverseContents is not None:

View File

@ -201,15 +201,15 @@ In alphabetical order:
Olivier Berten, Samyak Bhuta, Erik van Blokland, Petr van Blokland,
Jelle Bosma, Sascha Brawer, Tom Byrer, Frédéric Coiffier, Vincent
Connare, David Corbett, Dave Crossland, Simon Daniels, Peter Dekkers,
Behdad Esfahbod, Behnam Esfahbod, Hannes Famira, Sam Fishman, Matt
Fontaine, Yannis Haralambous, Greg Hitchcock, Jeremie Hornus, Khaled
Hosny, John Hudson, Denis Moyogo Jacquerye, Jack Jansen, Tom Kacvinsky,
Jens Kutilek, Antoine Leca, Werner Lemberg, Tal Leming, Peter Lofting,
Cosimo Lupo, Masaya Nakamura, Dave Opstad, Laurence Penney, Roozbeh
Pournader, Garret Rieger, Read Roberts, Guido van Rossum, Just van
Rossum, Andreas Seidel, Georg Seifert, Chris Simpkins, Miguel Sousa,
Adam Twardoch, Adrien Tétar, Vitaly Volkov, Paul Wise.
Connare, David Corbett, Simon Cozens, Dave Crossland, Simon Daniels,
Peter Dekkers, Behdad Esfahbod, Behnam Esfahbod, Hannes Famira, Sam
Fishman, Matt Fontaine, Yannis Haralambous, Greg Hitchcock, Jeremie
Hornus, Khaled Hosny, John Hudson, Denis Moyogo Jacquerye, Jack Jansen,
Tom Kacvinsky, Jens Kutilek, Antoine Leca, Werner Lemberg, Tal Leming,
Peter Lofting, Cosimo Lupo, Masaya Nakamura, Dave Opstad, Laurence
Penney, Roozbeh Pournader, Garret Rieger, Read Roberts, Guido van
Rossum, Just van Rossum, Andreas Seidel, Georg Seifert, Chris Simpkins,
Miguel Sousa, Adam Twardoch, Adrien Tétar, Vitaly Volkov, Paul Wise.
Copyrights
~~~~~~~~~~

View File

@ -495,14 +495,6 @@ class BuilderTest(object):
),
) as excinfo:
builder.buildLookup([s], builder.LOOKUP_FLAG_USE_MARK_FILTERING_SET, None)
with pytest.raises(
AssertionError,
match=(
"if markFilterSet is not None, flags must set "
"LOOKUP_FLAG_USE_MARK_FILTERING_SET; flags=0x0004"
),
) as excinfo:
builder.buildLookup([s], builder.LOOKUP_FLAG_IGNORE_LIGATURES, 777)
def test_buildLookup_conflictingSubtableTypes(self):
s1 = builder.buildSingleSubstSubtable({"one": "two"})

View File

@ -111,34 +111,56 @@ class GlyphSetTests(unittest.TestCase):
self.assertEqual(g.unicodes, unicodes[glyphName])
class FileNameTests(unittest.TestCase):
class FileNameTest:
def testDefaultFileNameScheme(self):
self.assertEqual(glyphNameToFileName("a", None), "a.glif")
self.assertEqual(glyphNameToFileName("A", None), "A_.glif")
self.assertEqual(glyphNameToFileName("Aring", None), "A_ring.glif")
self.assertEqual(glyphNameToFileName("F_A_B", None), "F__A__B_.glif")
self.assertEqual(glyphNameToFileName("A.alt", None), "A_.alt.glif")
self.assertEqual(glyphNameToFileName("A.Alt", None), "A_.A_lt.glif")
self.assertEqual(glyphNameToFileName(".notdef", None), "_notdef.glif")
self.assertEqual(glyphNameToFileName("T_H", None), "T__H_.glif")
self.assertEqual(glyphNameToFileName("T_h", None), "T__h.glif")
self.assertEqual(glyphNameToFileName("t_h", None), "t_h.glif")
self.assertEqual(glyphNameToFileName("F_F_I", None), "F__F__I_.glif")
self.assertEqual(glyphNameToFileName("f_f_i", None), "f_f_i.glif")
self.assertEqual(glyphNameToFileName("AE", None), "A_E_.glif")
self.assertEqual(glyphNameToFileName("Ae", None), "A_e.glif")
self.assertEqual(glyphNameToFileName("ae", None), "ae.glif")
self.assertEqual(glyphNameToFileName("aE", None), "aE_.glif")
self.assertEqual(glyphNameToFileName("a.alt", None), "a.alt.glif")
self.assertEqual(glyphNameToFileName("A.aLt", None), "A_.aL_t.glif")
self.assertEqual(glyphNameToFileName("A.alT", None), "A_.alT_.glif")
self.assertEqual(glyphNameToFileName("Aacute_V.swash", None), "A_acute_V_.swash.glif")
self.assertEqual(glyphNameToFileName(".notdef", None), "_notdef.glif")
self.assertEqual(glyphNameToFileName("con", None), "_con.glif")
self.assertEqual(glyphNameToFileName("CON", None), "C_O_N_.glif")
self.assertEqual(glyphNameToFileName("con.alt", None), "_con.alt.glif")
self.assertEqual(glyphNameToFileName("alt.con", None), "alt._con.glif")
def test_default_file_name_scheme(self):
assert glyphNameToFileName("a", None) == "a.glif"
assert glyphNameToFileName("A", None) == "A_.glif"
assert glyphNameToFileName("Aring", None) == "A_ring.glif"
assert glyphNameToFileName("F_A_B", None) == "F__A__B_.glif"
assert glyphNameToFileName("A.alt", None) == "A_.alt.glif"
assert glyphNameToFileName("A.Alt", None) == "A_.A_lt.glif"
assert glyphNameToFileName(".notdef", None) == "_notdef.glif"
assert glyphNameToFileName("T_H", None) =="T__H_.glif"
assert glyphNameToFileName("T_h", None) =="T__h.glif"
assert glyphNameToFileName("t_h", None) =="t_h.glif"
assert glyphNameToFileName("F_F_I", None) == "F__F__I_.glif"
assert glyphNameToFileName("f_f_i", None) == "f_f_i.glif"
assert glyphNameToFileName("AE", None) == "A_E_.glif"
assert glyphNameToFileName("Ae", None) == "A_e.glif"
assert glyphNameToFileName("ae", None) == "ae.glif"
assert glyphNameToFileName("aE", None) == "aE_.glif"
assert glyphNameToFileName("a.alt", None) == "a.alt.glif"
assert glyphNameToFileName("A.aLt", None) == "A_.aL_t.glif"
assert glyphNameToFileName("A.alT", None) == "A_.alT_.glif"
assert glyphNameToFileName("Aacute_V.swash", None) == "A_acute_V_.swash.glif"
assert glyphNameToFileName(".notdef", None) == "_notdef.glif"
assert glyphNameToFileName("con", None) == "_con.glif"
assert glyphNameToFileName("CON", None) == "C_O_N_.glif"
assert glyphNameToFileName("con.alt", None) == "_con.alt.glif"
assert glyphNameToFileName("alt.con", None) == "alt._con.glif"
def test_conflicting_case_insensitive_file_names(self, tmp_path):
src = GlyphSet(GLYPHSETDIR)
dst = GlyphSet(tmp_path)
glyph = src["a"]
dst.writeGlyph("a", glyph)
dst.writeGlyph("A", glyph)
dst.writeGlyph("a_", glyph)
dst.writeGlyph("A_", glyph)
dst.writeGlyph("i_j", glyph)
assert dst.contents == {
'a': 'a.glif',
'A': 'A_.glif',
'a_': 'a_000000000000001.glif',
'A_': 'A__.glif',
'i_j': 'i_j.glif',
}
# make sure filenames are unique even on case-insensitive filesystems
assert len({fileName.lower() for fileName in dst.contents.values()}) == 5
class _Glyph: