Merge remote-tracking branch 'origin/master' into colrv1-rev2
This commit is contained in:
commit
64731aedd0
@ -1,8 +0,0 @@
|
||||
#######
|
||||
builder
|
||||
#######
|
||||
|
||||
.. automodule:: fontTools.otlLib.builder
|
||||
:inherited-members:
|
||||
:members:
|
||||
:undoc-members:
|
@ -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
|
||||
|
@ -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
@ -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:
|
||||
|
18
README.rst
18
README.rst
@ -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
|
||||
~~~~~~~~~~
|
||||
|
@ -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"})
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user