Beispiel #1
0
 def test_compile_version_11_as_float(self):
     vhea = self.font['vhea']
     vhea.tableVersion = 1.0625
     with CapturingLogHandler(log, "WARNING") as captor:
         self.assertEqual(VHEA_DATA_VERSION_11, vhea.compile(self.font))
     self.assertTrue(
         len([r for r in captor.records
              if "Table version value is a float" in r.msg]) == 1)
Beispiel #2
0
 def test_pairPos_enumRuleOverridenBySinglePair_DEBUG(self):
     logger = logging.getLogger("fontTools.otlLib.builder")
     with CapturingLogHandler(logger, "DEBUG") as captor:
         self.build("feature test {"
                    "    enum pos A [V Y] -80;"
                    "    pos A V -75;"
                    "} test;")
     captor.assertRegex("Already defined position for pair A V at")
	def test_addMultilingualName_noTTFont(self):
		# If the ttFont argument is not passed, the implementation
		# should add whatever names it can, but it should not crash
		# just because it cannot build an ltag table.
		nameTable = newTable("name")
		with CapturingLogHandler(log, "WARNING") as captor:
			nameTable.addMultilingualName({"en": "A", "la": "ⱾƤℚⱤ"})
		captor.assertRegex("cannot store language la into 'ltag' table")
    def test_dangling_layer(self):
        self.font.glyphs[0].layers[0].layerId = "yyy"
        self.font.glyphs[0].layers[0].associatedMasterId = "xxx"

        with CapturingLogHandler(self.logger, level="WARNING") as captor:
            to_ufos(self.font, minimize_glyphs_diffs=True)

        captor.assertRegex("is dangling and will be skipped")
Beispiel #5
0
 def test_compile_version_10_as_float(self):
     hhea = self.font['hhea']
     hhea.tableVersion = 1.0
     with CapturingLogHandler(log, "WARNING") as captor:
         self.assertEqual(HHEA_DATA, hhea.compile(self.font))
     self.assertTrue(
         len([r for r in captor.records
              if "Table version value is a float" in r.msg]) == 1)
Beispiel #6
0
 def test_toXML_version_as_float(self):
     hhea = self.font['hhea']
     hhea.tableVersion = 1.0
     with CapturingLogHandler(log, "WARNING") as captor:
         self.assertEqual(getXML(hhea.toXML), HHEA_XML)
     self.assertTrue(
         len([r for r in captor.records
              if "Table version value is a float" in r.msg]) == 1)
Beispiel #7
0
 def test_toXML_version_11_as_float(self):
     vhea = self.font['vhea']
     vhea.tableVersion = 1.0625
     with CapturingLogHandler(log, "WARNING") as captor:
         self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_11)
     self.assertTrue(
         len([r for r in captor.records
              if "Table version value is a float" in r.msg]) == 1)
Beispiel #8
0
 def test_read_replace_not_ascii(self):
     reader = OTTableReader(b"Hello \xE4 world" + 100 * b"\0")
     with CapturingLogHandler(otConverters.log, "WARNING") as captor:
         data = self.converter.read(reader, self.font, {})
     self.assertEqual(data, "Hello � world")
     self.assertEqual(reader.pos, 64)
     self.assertIn('replaced non-ASCII characters in "Hello � world"',
                   [r.msg for r in captor.records])
Beispiel #9
0
    def test_decompile_too_much_data(self):
        font = self.makeFont(numGlyphs=1, numberOfMetrics=1)
        mtxTable = newTable(self.tag)
        msg = "too much '%s' table data" % self.tag

        with CapturingLogHandler(log, "WARNING") as captor:
            mtxTable.decompile(b"\0\0\0\0\0", font)

        self.assertTrue(len([r for r in captor.records if msg == r.msg]) == 1)
Beispiel #10
0
    def test_normal_layer(self):
        with CapturingLogHandler(self.logger, level="WARNING") as captor:
            to_ufos(self.font)

        # no warnings are emitted
        self.assertRaises(AssertionError, captor.assertRegex,
                          "is dangling and will be skipped")
        self.assertRaises(AssertionError, captor.assertRegex,
                          "layer without a name")
Beispiel #11
0
	def test_decompilePoints_shouldAcceptBadPointNumbers(self):
		decompilePoints = TupleVariation.decompilePoints_
		# 2 points; first run: [3, 9].
		numPointsInGlyph = 8
		with CapturingLogHandler(log, "WARNING") as captor:
			decompilePoints(numPointsInGlyph,
			                deHexStr("02 01 03 06"), 0, "cvar")
		self.assertIn("point 9 out of range in 'cvar' table",
		              [r.msg for r in captor.records])
Beispiel #12
0
    def test_warn_no_version(self):
        """Test that a warning is printed when app version is missing."""

        font = generate_minimal_font()
        font.appVersion = "0"
        with CapturingLogHandler(builder.logger, "WARNING") as captor:
            to_ufos(font)
        self.assertEqual(
            len([r for r in captor.records if "outdated version" in r.msg]), 1)
Beispiel #13
0
 def test_fromXML_version_as_float(self):
     hhea = self.font['hhea']
     with CapturingLogHandler(log, "WARNING") as captor:
         for name, attrs, content in parseXML(HHEA_XML_VERSION_AS_FLOAT):
             hhea.fromXML(name, attrs, content, self.font)
     self.assertTrue(
         len([r for r in captor.records
              if "Table version value is a float" in r.msg]) == 1)
     for key in hhea.__dict__:
         self.assertEqual(getattr(hhea, key), HHEA_AS_DICT[key])
Beispiel #14
0
 def test_empty_string(self):
     inputstr = ''
     with CapturingLogHandler(builder.logger, "ERROR") as captor:
         result = parse_glyphs_filter(inputstr)
     self.assertGreater(len([
         r for r in captor.records
         if 'Failed to parse glyphs filter' in r.msg
     ]),
                        0,
                        msg='Empty string should trigger an error message')
Beispiel #15
0
    def test_decompile_num_metrics_greater_than_glyphs(self):
        font = self.makeFont(numGlyphs=1, numberOfMetrics=2)
        mtxTable = newTable(self.tag)
        msg = "The %s.%s exceeds the maxp.numGlyphs" % (
            self.tableClass.headerTag, self.tableClass.numberOfMetricsName)

        with CapturingLogHandler(log, "WARNING") as captor:
            mtxTable.decompile(b"\0\0\0\0", font)

        self.assertTrue(len([r for r in captor.records if msg == r.msg]) == 1)
Beispiel #16
0
 def test_multipleSubst_multipleIdenticalSubstitutionsForSameGlyph_info(self):
     logger = logging.getLogger("fontTools.feaLib.builder")
     with CapturingLogHandler(logger, "INFO") as captor:
         self.build(
             "feature test {"
             "    sub f_f_i by f f i;"
             "    sub c_t by c t;"
             "    sub f_f_i by f f i;"
             "} test;")
     captor.assertRegex(r"Removing duplicate multiple substitution from glyph \"f_f_i\" to \('f', 'f', 'i'\)")
Beispiel #17
0
 def test_singleSubst_multipleIdenticalSubstitutionsForSameGlyph_info(self):
     logger = logging.getLogger("fontTools.feaLib.builder")
     with CapturingLogHandler(logger, "INFO") as captor:
         self.build("feature test {"
                    "    sub A by A.sc;"
                    "    sub B by B.sc;"
                    "    sub A by A.sc;"
                    "} test;")
     captor.assertRegex(
         'Removing duplicate single substitution from glyph "A" to "A.sc"')
 def test_no_name(self):
     inputstr = ";OffsetX:2"
     with CapturingLogHandler(builder.logger, "ERROR") as captor:
         parse_glyphs_filter(inputstr)
     self.assertGreater(
         len(
             [r for r in captor.records if "Failed to parse glyphs filter" in r.msg]
         ),
         0,
         msg="Empty string with no filter name should trigger an error message",
     )
 def test_xmlWrite_missingID(self):
     writer = makeXMLWriter()
     with CapturingLogHandler(otConverters.log, "WARNING") as captor:
         self.converter.xmlWrite(writer, self.makeFont(), 666, "Entity",
                                 [("attrib", "val")])
     self.assertIn("name id 666 missing from name table",
                   [r.msg for r in captor.records])
     xml = writer.file.getvalue().decode("utf-8").rstrip()
     self.assertEqual(
         xml, '<Entity attrib="val"'
         ' value="666"/>  <!-- missing from name table -->')
Beispiel #20
0
	def test_toXML_badDeltaFormat(self):
		writer = XMLWriter(BytesIO())
		g = TupleVariation(AXES, ["String"])
		with CapturingLogHandler(log, "ERROR") as captor:
			g.toXML(writer, ["wdth"])
		self.assertIn("bad delta format", [r.msg for r in captor.records])
		self.assertEqual([
			'<tuple>',
			  '<coord axis="wdth" min="0.3" value="0.4" max="0.5"/>',
			  '<!-- bad delta #0 -->',
			'</tuple>',
		], TupleVariationTest.xml_lines(writer))
Beispiel #21
0
    def test_GSUB_merge_with_different_dups_and_no_second_GSUB(self):
        self.table2 = NotImplemented
        self.merger.duplicateGlyphsPerFont = [{}, {'uni0032#0': 'uni0032#1'}]
        self.merger.fonts = []
        self.merger.fontfiles = ['font1', 'font2']
        with mockIsGlyphSame(False):
            with CapturingLogHandler(fontTools.merge.log, "WARNING") as captor:
                self.mergedTable.merge(self.merger, [self.table1, self.table2])

        table = self.mergedTable.table
        self.assertEqual(table, self.table1.table)
        self.assertTrue(len([r for r in captor.records if r.msg != '']) > 0)
Beispiel #22
0
    def test_compile_negative_advance(self):
        font = self.makeFont(numGlyphs=1, numberOfMetrics=1)
        mtxTable = font[self.tag] = newTable(self.tag)
        mtxTable.metrics = {'A': [-1, 0]}

        with CapturingLogHandler(log, "ERROR") as captor:
            with self.assertRaisesRegex(TTLibError, "negative advance"):
                mtxTable.compile(font)

        self.assertTrue(
            len([r for r in captor.records
                if "Glyph 'A' has negative advance" in r.msg]) == 1)
Beispiel #23
0
    def test_unsupported_subtable_break(self):
        logger = logging.getLogger("fontTools.otlLib.builder")
        with CapturingLogHandler(logger, level='WARNING') as captor:
            self.build("feature test {"
                       "    pos a 10;"
                       "    subtable;"
                       "    pos b 10;"
                       "} test;")

        captor.assertRegex(
            '<features>:1:32: unsupported "subtable" statement for lookup type'
        )
Beispiel #24
0
def test_unsupported_subtable_break_1(ttfont):
    location = MockBuilderLocation((0, "alpha"))

    logger = logging.getLogger("fontTools.otlLib.builder")

    with CapturingLogHandler(logger, "INFO") as captor:
        builder = SinglePosBuilder(ttfont, location)
        builder.add_subtable_break(MockBuilderLocation((5, "beta")))
        builder.build()

    captor.assertRegex(
        '5:beta: unsupported "subtable" statement for lookup type')
    def test_duplicate_exclude_include(self):
        inputstr = 'thisisaname;34;-3.4;exclude:uni1111;include:uni0022;exclude:uni2222'
        expected = {
            'name': 'thisisaname',
            'args': [34, -3.4],
            'exclude': ['uni2222'],
        }
        with CapturingLogHandler(builder.logger, "ERROR") as captor:
            result = parse_glyphs_filter(inputstr)

        self.assertGreater(len([r for r in captor.records if 'can only present as the last argument' in r.msg]), 0,
            msg='The parse_glyphs_filter should warn user that the exclude/include should only be the last argument in the filter string.')
        self.assertEqual(result, expected)
Beispiel #26
0
    def test_decompile_possibly_negative_advance(self):
        font = self.makeFont(numGlyphs=1, numberOfMetrics=1)
        # we warn if advance is > 0x7FFF as it might be interpreted as signed
        # by some authoring tools
        data = deHexStr("8000 0000")
        mtxTable = newTable(self.tag)

        with CapturingLogHandler(log, "WARNING") as captor:
            mtxTable.decompile(data, font)

        self.assertTrue(
            len([r for r in captor.records
                 if "has a huge advance" in r.msg]) == 1)
Beispiel #27
0
def test_decompile_offset_past_end(empty_font):
    empty_font.glyphOrder = ['foo', 'bar']
    content = 'baz'
    data = tobytes(content)
    empty_font['TSI0'].indices = [(0, len(data), 0), (1, 1, len(data) + 1)]

    table = table_T_S_I__1()
    with CapturingLogHandler(table.log, "WARNING") as captor:
        table.decompile(data, empty_font)

    # the 'bar' program is skipped because its offset > len(data)
    assert table.glyphPrograms == {'foo': 'baz'}
    assert any("textOffset > totalLength" in r.msg for r in captor.records)
Beispiel #28
0
 def test_addMultilingualName_legacyMacEncoding(self):
     # Windows has no language code for Latin; MacOS has a code;
     # and we actually can convert the name to the legacy MacRoman
     # encoding. In this case, we expect that the name gets encoded
     # as Macintosh name (platformID 1) with the corresponding Mac
     # language code (133); the 'ltag' table should not be used.
     font = FakeFont(glyphs=[".notdef", "A"])
     nameTable = font.tables['name'] = newTable("name")
     with CapturingLogHandler(log, "WARNING") as captor:
         nameTable.addMultilingualName({"la": "SPQR"}, ttFont=font)
     captor.assertRegex("cannot add Windows name in language la")
     self.assertEqual(names(nameTable), [(256, 1, 0, 131, "SPQR")])
     self.assertNotIn("ltag", font.tables.keys())
Beispiel #29
0
 def test_addMultilingualName_legacyMacEncodingButUnencodableName(self):
     # Windows has no language code for Latin; MacOS has a code;
     # but we cannot encode the name into this encoding because
     # it contains characters that are not representable.
     # In this case, we expect that the name gets encoded as
     # Unicode name (platformID 0) with the language tag being
     # added to the 'ltag' table.
     font = FakeFont(glyphs=[".notdef", "A"])
     nameTable = font.tables['name'] = newTable("name")
     with CapturingLogHandler(log, "WARNING") as captor:
         nameTable.addMultilingualName({"la": "ⱾƤℚⱤ"}, ttFont=font)
     captor.assertRegex("cannot add Windows name in language la")
     self.assertEqual(names(nameTable), [(256, 0, 4, 0, "ⱾƤℚⱤ")])
     self.assertIn("ltag", font.tables)
     self.assertEqual(font["ltag"].tags, ["la"])
Beispiel #30
0
    def test_save_in_place_invalid_ufo(self):
        path = makeTestFontCopy()
        font = Font(path)
        layercontents = os.path.join(path, "layercontents.plist")
        os.remove(layercontents)
        self.assertFalse(os.path.exists(layercontents))

        logger = logging.getLogger("defcon.objects.font")
        with CapturingLogHandler(logger, level="ERROR") as captor:
            font.save()
        captor.assertRegex("Invalid ufo found")

        self.assertTrue(os.path.exists(layercontents))
        font = Font(path)
        _ = font.layers
        font.save()