コード例 #1
0
def compact_class_pairs(font: TTFont, mode: str,
                        subtable: otTables.PairPos) -> List[otTables.PairPos]:
    from fontTools.otlLib.builder import buildPairPosClassesSubtable

    subtables = []
    classes1: DefaultDict[int, List[str]] = defaultdict(list)
    for g in subtable.Coverage.glyphs:
        classes1[subtable.ClassDef1.classDefs.get(g, 0)].append(g)
    classes2: DefaultDict[int, List[str]] = defaultdict(list)
    for g, i in subtable.ClassDef2.classDefs.items():
        classes2[i].append(g)
    all_pairs = {}
    for i, class1 in enumerate(subtable.Class1Record):
        for j, class2 in enumerate(class1.Class2Record):
            if is_really_zero(class2):
                continue
            all_pairs[(tuple(sorted(classes1[i])),
                       tuple(sorted(classes2[j])))] = (
                           getattr(class2, "Value1", None),
                           getattr(class2, "Value2", None),
                       )

    if len(mode) == 1 and mode in "123456789":
        grouped_pairs = cluster_pairs_by_class2_coverage_custom_cost(
            font, all_pairs, int(mode))
        for pairs in grouped_pairs:
            subtables.append(
                buildPairPosClassesSubtable(pairs, font.getReverseGlyphMap()))
    else:
        raise ValueError(f"Bad {GPOS_COMPACT_MODE_ENV_KEY}={mode}")
    return subtables
コード例 #2
0
def compact_class_pairs(
    font: TTFont, level: int, subtable: otTables.PairPos
) -> List[otTables.PairPos]:
    from fontTools.otlLib.builder import buildPairPosClassesSubtable

    subtables = []
    classes1: DefaultDict[int, List[str]] = defaultdict(list)
    for g in subtable.Coverage.glyphs:
        classes1[subtable.ClassDef1.classDefs.get(g, 0)].append(g)
    classes2: DefaultDict[int, List[str]] = defaultdict(list)
    for g, i in subtable.ClassDef2.classDefs.items():
        classes2[i].append(g)
    all_pairs = {}
    for i, class1 in enumerate(subtable.Class1Record):
        for j, class2 in enumerate(class1.Class2Record):
            if is_really_zero(class2):
                continue
            all_pairs[(tuple(sorted(classes1[i])), tuple(sorted(classes2[j])))] = (
                getattr(class2, "Value1", None),
                getattr(class2, "Value2", None),
            )
    grouped_pairs = cluster_pairs_by_class2_coverage_custom_cost(font, all_pairs, level)
    for pairs in grouped_pairs:
        subtables.append(buildPairPosClassesSubtable(pairs, font.getReverseGlyphMap()))
    return subtables
コード例 #3
0
 def test_buildPairPosClassesSubtable(self):
     d20 = builder.buildValue({"XPlacement": -20})
     d50 = builder.buildValue({"XPlacement": -50})
     d0 = builder.buildValue({})
     d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20})
     subtable = builder.buildPairPosClassesSubtable(
         {
             (tuple("A"), tuple(["zero"])): (d0, d50),
             (tuple("A"), tuple(["one", "two"])): (None, d20),
             (tuple(["B", "C"]), tuple(["zero"])): (d8020, d50),
         },
         self.GLYPHMAP,
     )
     assert getXML(subtable.toXML) == [
         '<PairPos Format="2">',
         "  <Coverage>",
         '    <Glyph value="A"/>',
         '    <Glyph value="B"/>',
         '    <Glyph value="C"/>',
         "  </Coverage>",
         '  <ValueFormat1 value="3"/>',
         '  <ValueFormat2 value="1"/>',
         "  <ClassDef1>",
         '    <ClassDef glyph="A" class="1"/>',
         "  </ClassDef1>",
         "  <ClassDef2>",
         '    <ClassDef glyph="one" class="1"/>',
         '    <ClassDef glyph="two" class="1"/>',
         '    <ClassDef glyph="zero" class="2"/>',
         "  </ClassDef2>",
         "  <!-- Class1Count=2 -->",
         "  <!-- Class2Count=3 -->",
         '  <Class1Record index="0">',
         '    <Class2Record index="0">',
         "    </Class2Record>",
         '    <Class2Record index="1">',
         "    </Class2Record>",
         '    <Class2Record index="2">',
         '      <Value1 XPlacement="-80" YPlacement="-20"/>',
         '      <Value2 XPlacement="-50"/>',
         "    </Class2Record>",
         "  </Class1Record>",
         '  <Class1Record index="1">',
         '    <Class2Record index="0">',
         "    </Class2Record>",
         '    <Class2Record index="1">',
         '      <Value2 XPlacement="-20"/>',
         "    </Class2Record>",
         '    <Class2Record index="2">',
         "      <Value1/>",
         '      <Value2 XPlacement="-50"/>',
         "    </Class2Record>",
         "  </Class1Record>",
         "</PairPos>",
     ]
コード例 #4
0
 def test_buildPairPosClassesSubtable(self):
     d20 = builder.buildValue({"XPlacement": -20})
     d50 = builder.buildValue({"XPlacement": -50})
     d0 = builder.buildValue({})
     d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20})
     subtable = builder.buildPairPosClassesSubtable(
         {
             (frozenset("A"), frozenset(["zero"])): (d0, d50),
             (frozenset("A"), frozenset(["one", "two"])): (None, d20),
             (frozenset(["B", "C"]), frozenset(["zero"])): (d8020, d50),
         }, self.GLYPHMAP)
     self.maxDiff = None
     self.assertEqual(
         getXML(subtable.toXML), '<PairPos Format="2">'
         '  <Coverage>'
         '    <Glyph value="A"/>'
         '    <Glyph value="B"/>'
         '    <Glyph value="C"/>'
         '  </Coverage>'
         '  <ValueFormat1 value="3"/>'
         '  <ValueFormat2 value="1"/>'
         '  <ClassDef1>'
         '    <ClassDef glyph="A" class="1"/>'
         '  </ClassDef1>'
         '  <ClassDef2>'
         '    <ClassDef glyph="one" class="1"/>'
         '    <ClassDef glyph="two" class="1"/>'
         '    <ClassDef glyph="zero" class="2"/>'
         '  </ClassDef2>'
         '  <!-- Class1Count=2 -->'
         '  <!-- Class2Count=3 -->'
         '  <Class1Record index="0">'
         '    <Class2Record index="0">'
         '    </Class2Record>'
         '    <Class2Record index="1">'
         '    </Class2Record>'
         '    <Class2Record index="2">'
         '      <Value1 XPlacement="-80" YPlacement="-20"/>'
         '      <Value2 XPlacement="-50"/>'
         '    </Class2Record>'
         '  </Class1Record>'
         '  <Class1Record index="1">'
         '    <Class2Record index="0">'
         '    </Class2Record>'
         '    <Class2Record index="1">'
         '      <Value2 XPlacement="-20"/>'
         '    </Class2Record>'
         '    <Class2Record index="2">'
         '      <Value1/>'
         '      <Value2 XPlacement="-50"/>'
         '    </Class2Record>'
         '  </Class1Record>'
         '</PairPos>')
コード例 #5
0
ファイル: builder_test.py プロジェクト: AndreDing/fonttools
 def test_buildPairPosClassesSubtable(self):
     d20 = builder.buildValue({"XPlacement": -20})
     d50 = builder.buildValue({"XPlacement": -50})
     d0 = builder.buildValue({})
     d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20})
     subtable = builder.buildPairPosClassesSubtable({
         (tuple("A",), tuple(["zero"])): (d0, d50),
         (tuple("A",), tuple(["one", "two"])):  (None, d20),
         (tuple(["B", "C"]), tuple(["zero"])): (d8020, d50),
     }, self.GLYPHMAP)
     self.maxDiff = None
     self.assertEqual(getXML(subtable.toXML),
                      '<PairPos Format="2">'
                      '  <Coverage>'
                      '    <Glyph value="A"/>'
                      '    <Glyph value="B"/>'
                      '    <Glyph value="C"/>'
                      '  </Coverage>'
                      '  <ValueFormat1 value="3"/>'
                      '  <ValueFormat2 value="1"/>'
                      '  <ClassDef1>'
                      '    <ClassDef glyph="A" class="1"/>'
                      '  </ClassDef1>'
                      '  <ClassDef2>'
                      '    <ClassDef glyph="one" class="1"/>'
                      '    <ClassDef glyph="two" class="1"/>'
                      '    <ClassDef glyph="zero" class="2"/>'
                      '  </ClassDef2>'
                      '  <!-- Class1Count=2 -->'
                      '  <!-- Class2Count=3 -->'
                      '  <Class1Record index="0">'
                      '    <Class2Record index="0">'
                      '    </Class2Record>'
                      '    <Class2Record index="1">'
                      '    </Class2Record>'
                      '    <Class2Record index="2">'
                      '      <Value1 XPlacement="-80" YPlacement="-20"/>'
                      '      <Value2 XPlacement="-50"/>'
                      '    </Class2Record>'
                      '  </Class1Record>'
                      '  <Class1Record index="1">'
                      '    <Class2Record index="0">'
                      '    </Class2Record>'
                      '    <Class2Record index="1">'
                      '      <Value2 XPlacement="-20"/>'
                      '    </Class2Record>'
                      '    <Class2Record index="2">'
                      '      <Value1/>'
                      '      <Value2 XPlacement="-50"/>'
                      '    </Class2Record>'
                      '  </Class1Record>'
                      '</PairPos>')
コード例 #6
0
ファイル: builder.py プロジェクト: shannonyu/fonttools
 def flush_(self):
     if self.classDef1_ is None or self.classDef2_ is None:
         return
     st = otl.buildPairPosClassesSubtable(self.values_,
                                          self.builder_.glyphMap)
     self.subtables_.append(st)
コード例 #7
0
ファイル: builder.py プロジェクト: jamesgk/fonttools
 def flush_(self):
     if self.classDef1_ is None or self.classDef2_ is None:
         return
     st = otl.buildPairPosClassesSubtable(self.values_, self.builder_.glyphMap)
     self.subtables_.append(st)