1*e1fe3e4aSElliott Hughesfrom fontTools.ttLib import TTFont, tagToXML 2*e1fe3e4aSElliott Hughesfrom io import StringIO 3*e1fe3e4aSElliott Hughesimport os 4*e1fe3e4aSElliott Hughesimport sys 5*e1fe3e4aSElliott Hughesimport re 6*e1fe3e4aSElliott Hughesimport contextlib 7*e1fe3e4aSElliott Hughesimport pytest 8*e1fe3e4aSElliott Hughes 9*e1fe3e4aSElliott Hughestry: 10*e1fe3e4aSElliott Hughes import unicodedata2 11*e1fe3e4aSElliott Hughesexcept ImportError: 12*e1fe3e4aSElliott Hughes if sys.version_info[:2] < (3, 6): 13*e1fe3e4aSElliott Hughes unicodedata2 = None 14*e1fe3e4aSElliott Hughes else: 15*e1fe3e4aSElliott Hughes # on 3.6 the built-in unicodedata is the same as unicodedata2 backport 16*e1fe3e4aSElliott Hughes import unicodedata 17*e1fe3e4aSElliott Hughes 18*e1fe3e4aSElliott Hughes unicodedata2 = unicodedata 19*e1fe3e4aSElliott Hughes 20*e1fe3e4aSElliott Hughes 21*e1fe3e4aSElliott Hughes# Font files in data/*.{o,t}tf; output gets compared to data/*.ttx.* 22*e1fe3e4aSElliott HughesTESTS = { 23*e1fe3e4aSElliott Hughes "aots/base.otf": ( 24*e1fe3e4aSElliott Hughes "CFF ", 25*e1fe3e4aSElliott Hughes "cmap", 26*e1fe3e4aSElliott Hughes "head", 27*e1fe3e4aSElliott Hughes "hhea", 28*e1fe3e4aSElliott Hughes "hmtx", 29*e1fe3e4aSElliott Hughes "maxp", 30*e1fe3e4aSElliott Hughes "name", 31*e1fe3e4aSElliott Hughes "OS/2", 32*e1fe3e4aSElliott Hughes "post", 33*e1fe3e4aSElliott Hughes ), 34*e1fe3e4aSElliott Hughes "aots/classdef1_font1.otf": ("GSUB",), 35*e1fe3e4aSElliott Hughes "aots/classdef1_font2.otf": ("GSUB",), 36*e1fe3e4aSElliott Hughes "aots/classdef1_font3.otf": ("GSUB",), 37*e1fe3e4aSElliott Hughes "aots/classdef1_font4.otf": ("GSUB",), 38*e1fe3e4aSElliott Hughes "aots/classdef2_font1.otf": ("GSUB",), 39*e1fe3e4aSElliott Hughes "aots/classdef2_font2.otf": ("GSUB",), 40*e1fe3e4aSElliott Hughes "aots/classdef2_font3.otf": ("GSUB",), 41*e1fe3e4aSElliott Hughes "aots/classdef2_font4.otf": ("GSUB",), 42*e1fe3e4aSElliott Hughes "aots/cmap0_font1.otf": ("cmap",), 43*e1fe3e4aSElliott Hughes "aots/cmap10_font1.otf": ("cmap",), 44*e1fe3e4aSElliott Hughes "aots/cmap10_font2.otf": ("cmap",), 45*e1fe3e4aSElliott Hughes "aots/cmap12_font1.otf": ("cmap",), 46*e1fe3e4aSElliott Hughes "aots/cmap14_font1.otf": ("cmap",), 47*e1fe3e4aSElliott Hughes "aots/cmap2_font1.otf": ("cmap",), 48*e1fe3e4aSElliott Hughes "aots/cmap4_font1.otf": ("cmap",), 49*e1fe3e4aSElliott Hughes "aots/cmap4_font2.otf": ("cmap",), 50*e1fe3e4aSElliott Hughes "aots/cmap4_font3.otf": ("cmap",), 51*e1fe3e4aSElliott Hughes "aots/cmap4_font4.otf": ("cmap",), 52*e1fe3e4aSElliott Hughes "aots/cmap6_font1.otf": ("cmap",), 53*e1fe3e4aSElliott Hughes "aots/cmap6_font2.otf": ("cmap",), 54*e1fe3e4aSElliott Hughes "aots/cmap8_font1.otf": ("cmap",), 55*e1fe3e4aSElliott Hughes "aots/cmap_composition_font1.otf": ("cmap",), 56*e1fe3e4aSElliott Hughes "aots/cmap_subtableselection_font1.otf": ("cmap",), 57*e1fe3e4aSElliott Hughes "aots/cmap_subtableselection_font2.otf": ("cmap",), 58*e1fe3e4aSElliott Hughes "aots/cmap_subtableselection_font3.otf": ("cmap",), 59*e1fe3e4aSElliott Hughes "aots/cmap_subtableselection_font4.otf": ("cmap",), 60*e1fe3e4aSElliott Hughes "aots/cmap_subtableselection_font5.otf": ("cmap",), 61*e1fe3e4aSElliott Hughes "aots/gpos1_1_lookupflag_f1.otf": ("GDEF", "GPOS"), 62*e1fe3e4aSElliott Hughes "aots/gpos1_1_simple_f1.otf": ("GPOS",), 63*e1fe3e4aSElliott Hughes "aots/gpos1_1_simple_f2.otf": ("GPOS",), 64*e1fe3e4aSElliott Hughes "aots/gpos1_1_simple_f3.otf": ("GPOS",), 65*e1fe3e4aSElliott Hughes "aots/gpos1_1_simple_f4.otf": ("GPOS",), 66*e1fe3e4aSElliott Hughes "aots/gpos1_2_font1.otf": ("GPOS",), 67*e1fe3e4aSElliott Hughes "aots/gpos1_2_font2.otf": ("GDEF", "GPOS"), 68*e1fe3e4aSElliott Hughes "aots/gpos2_1_font6.otf": ("GPOS",), 69*e1fe3e4aSElliott Hughes "aots/gpos2_1_font7.otf": ("GPOS",), 70*e1fe3e4aSElliott Hughes "aots/gpos2_1_lookupflag_f1.otf": ("GDEF", "GPOS"), 71*e1fe3e4aSElliott Hughes "aots/gpos2_1_lookupflag_f2.otf": ("GDEF", "GPOS"), 72*e1fe3e4aSElliott Hughes "aots/gpos2_1_next_glyph_f1.otf": ("GPOS",), 73*e1fe3e4aSElliott Hughes "aots/gpos2_1_next_glyph_f2.otf": ("GPOS",), 74*e1fe3e4aSElliott Hughes "aots/gpos2_1_simple_f1.otf": ("GPOS",), 75*e1fe3e4aSElliott Hughes "aots/gpos2_2_font1.otf": ("GPOS",), 76*e1fe3e4aSElliott Hughes "aots/gpos2_2_font2.otf": ("GDEF", "GPOS"), 77*e1fe3e4aSElliott Hughes "aots/gpos2_2_font3.otf": ("GDEF", "GPOS"), 78*e1fe3e4aSElliott Hughes "aots/gpos2_2_font4.otf": ("GPOS",), 79*e1fe3e4aSElliott Hughes "aots/gpos2_2_font5.otf": ("GPOS",), 80*e1fe3e4aSElliott Hughes "aots/gpos3_font1.otf": ("GPOS",), 81*e1fe3e4aSElliott Hughes "aots/gpos3_font2.otf": ("GDEF", "GPOS"), 82*e1fe3e4aSElliott Hughes "aots/gpos3_font3.otf": ("GDEF", "GPOS"), 83*e1fe3e4aSElliott Hughes "aots/gpos4_lookupflag_f1.otf": ("GDEF", "GPOS"), 84*e1fe3e4aSElliott Hughes "aots/gpos4_lookupflag_f2.otf": ("GDEF", "GPOS"), 85*e1fe3e4aSElliott Hughes "aots/gpos4_multiple_anchors_1.otf": ("GDEF", "GPOS"), 86*e1fe3e4aSElliott Hughes "aots/gpos4_simple_1.otf": ("GDEF", "GPOS"), 87*e1fe3e4aSElliott Hughes "aots/gpos5_font1.otf": ("GDEF", "GPOS", "GSUB"), 88*e1fe3e4aSElliott Hughes "aots/gpos6_font1.otf": ("GDEF", "GPOS"), 89*e1fe3e4aSElliott Hughes "aots/gpos7_1_font1.otf": ("GPOS",), 90*e1fe3e4aSElliott Hughes "aots/gpos9_font1.otf": ("GPOS",), 91*e1fe3e4aSElliott Hughes "aots/gpos9_font2.otf": ("GPOS",), 92*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_boundary_f1.otf": ("GDEF", "GPOS"), 93*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_boundary_f2.otf": ("GDEF", "GPOS"), 94*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_boundary_f3.otf": ("GDEF", "GPOS"), 95*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_boundary_f4.otf": ("GDEF", "GPOS"), 96*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_lookupflag_f1.otf": ("GDEF", "GPOS"), 97*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_multiple_subrules_f1.otf": ("GDEF", "GPOS"), 98*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_multiple_subrules_f2.otf": ("GDEF", "GPOS"), 99*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_next_glyph_f1.otf": ("GDEF", "GPOS"), 100*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_simple_f1.otf": ("GDEF", "GPOS"), 101*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_simple_f2.otf": ("GDEF", "GPOS"), 102*e1fe3e4aSElliott Hughes "aots/gpos_chaining1_successive_f1.otf": ("GDEF", "GPOS"), 103*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_boundary_f1.otf": ("GDEF", "GPOS"), 104*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_boundary_f2.otf": ("GDEF", "GPOS"), 105*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_boundary_f3.otf": ("GDEF", "GPOS"), 106*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_boundary_f4.otf": ("GDEF", "GPOS"), 107*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_lookupflag_f1.otf": ("GDEF", "GPOS"), 108*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_multiple_subrules_f1.otf": ("GDEF", "GPOS"), 109*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_multiple_subrules_f2.otf": ("GDEF", "GPOS"), 110*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_next_glyph_f1.otf": ("GDEF", "GPOS"), 111*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_simple_f1.otf": ("GDEF", "GPOS"), 112*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_simple_f2.otf": ("GDEF", "GPOS"), 113*e1fe3e4aSElliott Hughes "aots/gpos_chaining2_successive_f1.otf": ("GDEF", "GPOS"), 114*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_boundary_f1.otf": ("GDEF", "GPOS"), 115*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_boundary_f2.otf": ("GDEF", "GPOS"), 116*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_boundary_f3.otf": ("GDEF", "GPOS"), 117*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_boundary_f4.otf": ("GDEF", "GPOS"), 118*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_lookupflag_f1.otf": ("GDEF", "GPOS"), 119*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_next_glyph_f1.otf": ("GDEF", "GPOS"), 120*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_simple_f1.otf": ("GDEF", "GPOS"), 121*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_simple_f2.otf": ("GDEF", "GPOS"), 122*e1fe3e4aSElliott Hughes "aots/gpos_chaining3_successive_f1.otf": ("GDEF", "GPOS"), 123*e1fe3e4aSElliott Hughes "aots/gpos_context1_boundary_f1.otf": ("GDEF", "GPOS"), 124*e1fe3e4aSElliott Hughes "aots/gpos_context1_boundary_f2.otf": ("GDEF", "GPOS"), 125*e1fe3e4aSElliott Hughes "aots/gpos_context1_expansion_f1.otf": ("GDEF", "GPOS"), 126*e1fe3e4aSElliott Hughes "aots/gpos_context1_lookupflag_f1.otf": ("GDEF", "GPOS"), 127*e1fe3e4aSElliott Hughes "aots/gpos_context1_lookupflag_f2.otf": ("GDEF", "GPOS"), 128*e1fe3e4aSElliott Hughes "aots/gpos_context1_multiple_subrules_f1.otf": ("GDEF", "GPOS"), 129*e1fe3e4aSElliott Hughes "aots/gpos_context1_multiple_subrules_f2.otf": ("GDEF", "GPOS"), 130*e1fe3e4aSElliott Hughes "aots/gpos_context1_next_glyph_f1.otf": ("GDEF", "GPOS"), 131*e1fe3e4aSElliott Hughes "aots/gpos_context1_simple_f1.otf": ("GDEF", "GPOS"), 132*e1fe3e4aSElliott Hughes "aots/gpos_context1_simple_f2.otf": ("GDEF", "GPOS"), 133*e1fe3e4aSElliott Hughes "aots/gpos_context1_successive_f1.otf": ("GDEF", "GPOS"), 134*e1fe3e4aSElliott Hughes "aots/gpos_context2_boundary_f1.otf": ("GDEF", "GPOS"), 135*e1fe3e4aSElliott Hughes "aots/gpos_context2_boundary_f2.otf": ("GDEF", "GPOS"), 136*e1fe3e4aSElliott Hughes "aots/gpos_context2_classes_f1.otf": ("GDEF", "GPOS"), 137*e1fe3e4aSElliott Hughes "aots/gpos_context2_classes_f2.otf": ("GDEF", "GPOS"), 138*e1fe3e4aSElliott Hughes "aots/gpos_context2_expansion_f1.otf": ("GDEF", "GPOS"), 139*e1fe3e4aSElliott Hughes "aots/gpos_context2_lookupflag_f1.otf": ("GDEF", "GPOS"), 140*e1fe3e4aSElliott Hughes "aots/gpos_context2_lookupflag_f2.otf": ("GDEF", "GPOS"), 141*e1fe3e4aSElliott Hughes "aots/gpos_context2_multiple_subrules_f1.otf": ("GDEF", "GPOS"), 142*e1fe3e4aSElliott Hughes "aots/gpos_context2_multiple_subrules_f2.otf": ("GDEF", "GPOS"), 143*e1fe3e4aSElliott Hughes "aots/gpos_context2_next_glyph_f1.otf": ("GDEF", "GPOS"), 144*e1fe3e4aSElliott Hughes "aots/gpos_context2_simple_f1.otf": ("GDEF", "GPOS"), 145*e1fe3e4aSElliott Hughes "aots/gpos_context2_simple_f2.otf": ("GDEF", "GPOS"), 146*e1fe3e4aSElliott Hughes "aots/gpos_context2_successive_f1.otf": ("GDEF", "GPOS"), 147*e1fe3e4aSElliott Hughes "aots/gpos_context3_boundary_f1.otf": ("GDEF", "GPOS"), 148*e1fe3e4aSElliott Hughes "aots/gpos_context3_boundary_f2.otf": ("GDEF", "GPOS"), 149*e1fe3e4aSElliott Hughes "aots/gpos_context3_lookupflag_f1.otf": ("GDEF", "GPOS"), 150*e1fe3e4aSElliott Hughes "aots/gpos_context3_lookupflag_f2.otf": ("GDEF", "GPOS"), 151*e1fe3e4aSElliott Hughes "aots/gpos_context3_next_glyph_f1.otf": ("GDEF", "GPOS"), 152*e1fe3e4aSElliott Hughes "aots/gpos_context3_simple_f1.otf": ("GDEF", "GPOS"), 153*e1fe3e4aSElliott Hughes "aots/gpos_context3_successive_f1.otf": ("GDEF", "GPOS"), 154*e1fe3e4aSElliott Hughes "aots/gsub1_1_lookupflag_f1.otf": ("GDEF", "GSUB"), 155*e1fe3e4aSElliott Hughes "aots/gsub1_1_modulo_f1.otf": ("GSUB",), 156*e1fe3e4aSElliott Hughes "aots/gsub1_1_simple_f1.otf": ("GSUB",), 157*e1fe3e4aSElliott Hughes "aots/gsub1_2_lookupflag_f1.otf": ("GDEF", "GSUB"), 158*e1fe3e4aSElliott Hughes "aots/gsub1_2_simple_f1.otf": ("GSUB",), 159*e1fe3e4aSElliott Hughes "aots/gsub2_1_lookupflag_f1.otf": ("GDEF", "GSUB"), 160*e1fe3e4aSElliott Hughes "aots/gsub2_1_multiple_sequences_f1.otf": ("GSUB",), 161*e1fe3e4aSElliott Hughes "aots/gsub2_1_simple_f1.otf": ("GSUB",), 162*e1fe3e4aSElliott Hughes "aots/gsub3_1_lookupflag_f1.otf": ("GDEF", "GSUB"), 163*e1fe3e4aSElliott Hughes "aots/gsub3_1_multiple_f1.otf": ("GSUB",), 164*e1fe3e4aSElliott Hughes "aots/gsub3_1_simple_f1.otf": ("GSUB",), 165*e1fe3e4aSElliott Hughes "aots/gsub4_1_lookupflag_f1.otf": ("GDEF", "GSUB"), 166*e1fe3e4aSElliott Hughes "aots/gsub4_1_multiple_ligatures_f1.otf": ("GSUB",), 167*e1fe3e4aSElliott Hughes "aots/gsub4_1_multiple_ligatures_f2.otf": ("GSUB",), 168*e1fe3e4aSElliott Hughes "aots/gsub4_1_multiple_ligsets_f1.otf": ("GSUB",), 169*e1fe3e4aSElliott Hughes "aots/gsub4_1_simple_f1.otf": ("GSUB",), 170*e1fe3e4aSElliott Hughes "aots/gsub7_font1.otf": ("GSUB",), 171*e1fe3e4aSElliott Hughes "aots/gsub7_font2.otf": ("GSUB",), 172*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_boundary_f1.otf": ("GDEF", "GSUB"), 173*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_boundary_f2.otf": ("GDEF", "GSUB"), 174*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_boundary_f3.otf": ("GDEF", "GSUB"), 175*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_boundary_f4.otf": ("GDEF", "GSUB"), 176*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_lookupflag_f1.otf": ("GDEF", "GSUB"), 177*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_multiple_subrules_f1.otf": ("GDEF", "GSUB"), 178*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_multiple_subrules_f2.otf": ("GDEF", "GSUB"), 179*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_next_glyph_f1.otf": ("GDEF", "GSUB"), 180*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_simple_f1.otf": ("GDEF", "GSUB"), 181*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_simple_f2.otf": ("GDEF", "GSUB"), 182*e1fe3e4aSElliott Hughes "aots/gsub_chaining1_successive_f1.otf": ("GDEF", "GSUB"), 183*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_boundary_f1.otf": ("GDEF", "GSUB"), 184*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_boundary_f2.otf": ("GDEF", "GSUB"), 185*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_boundary_f3.otf": ("GDEF", "GSUB"), 186*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_boundary_f4.otf": ("GDEF", "GSUB"), 187*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_lookupflag_f1.otf": ("GDEF", "GSUB"), 188*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_multiple_subrules_f1.otf": ("GDEF", "GSUB"), 189*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_multiple_subrules_f2.otf": ("GDEF", "GSUB"), 190*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_next_glyph_f1.otf": ("GDEF", "GSUB"), 191*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_simple_f1.otf": ("GDEF", "GSUB"), 192*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_simple_f2.otf": ("GDEF", "GSUB"), 193*e1fe3e4aSElliott Hughes "aots/gsub_chaining2_successive_f1.otf": ("GDEF", "GSUB"), 194*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_boundary_f1.otf": ("GDEF", "GSUB"), 195*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_boundary_f2.otf": ("GDEF", "GSUB"), 196*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_boundary_f3.otf": ("GDEF", "GSUB"), 197*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_boundary_f4.otf": ("GDEF", "GSUB"), 198*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_lookupflag_f1.otf": ("GDEF", "GSUB"), 199*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_next_glyph_f1.otf": ("GDEF", "GSUB"), 200*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_simple_f1.otf": ("GDEF", "GSUB"), 201*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_simple_f2.otf": ("GDEF", "GSUB"), 202*e1fe3e4aSElliott Hughes "aots/gsub_chaining3_successive_f1.otf": ("GDEF", "GSUB"), 203*e1fe3e4aSElliott Hughes "aots/gsub_context1_boundary_f1.otf": ("GDEF", "GSUB"), 204*e1fe3e4aSElliott Hughes "aots/gsub_context1_boundary_f2.otf": ("GDEF", "GSUB"), 205*e1fe3e4aSElliott Hughes "aots/gsub_context1_expansion_f1.otf": ("GDEF", "GSUB"), 206*e1fe3e4aSElliott Hughes "aots/gsub_context1_lookupflag_f1.otf": ("GDEF", "GSUB"), 207*e1fe3e4aSElliott Hughes "aots/gsub_context1_lookupflag_f2.otf": ("GDEF", "GSUB"), 208*e1fe3e4aSElliott Hughes "aots/gsub_context1_multiple_subrules_f1.otf": ("GDEF", "GSUB"), 209*e1fe3e4aSElliott Hughes "aots/gsub_context1_multiple_subrules_f2.otf": ("GDEF", "GSUB"), 210*e1fe3e4aSElliott Hughes "aots/gsub_context1_next_glyph_f1.otf": ("GDEF", "GSUB"), 211*e1fe3e4aSElliott Hughes "aots/gsub_context1_simple_f1.otf": ("GDEF", "GSUB"), 212*e1fe3e4aSElliott Hughes "aots/gsub_context1_simple_f2.otf": ("GDEF", "GSUB"), 213*e1fe3e4aSElliott Hughes "aots/gsub_context1_successive_f1.otf": ("GDEF", "GSUB"), 214*e1fe3e4aSElliott Hughes "aots/gsub_context2_boundary_f1.otf": ("GDEF", "GSUB"), 215*e1fe3e4aSElliott Hughes "aots/gsub_context2_boundary_f2.otf": ("GDEF", "GSUB"), 216*e1fe3e4aSElliott Hughes "aots/gsub_context2_classes_f1.otf": ("GDEF", "GSUB"), 217*e1fe3e4aSElliott Hughes "aots/gsub_context2_classes_f2.otf": ("GDEF", "GSUB"), 218*e1fe3e4aSElliott Hughes "aots/gsub_context2_expansion_f1.otf": ("GDEF", "GSUB"), 219*e1fe3e4aSElliott Hughes "aots/gsub_context2_lookupflag_f1.otf": ("GDEF", "GSUB"), 220*e1fe3e4aSElliott Hughes "aots/gsub_context2_lookupflag_f2.otf": ("GDEF", "GSUB"), 221*e1fe3e4aSElliott Hughes "aots/gsub_context2_multiple_subrules_f1.otf": ("GDEF", "GSUB"), 222*e1fe3e4aSElliott Hughes "aots/gsub_context2_multiple_subrules_f2.otf": ("GDEF", "GSUB"), 223*e1fe3e4aSElliott Hughes "aots/gsub_context2_next_glyph_f1.otf": ("GDEF", "GSUB"), 224*e1fe3e4aSElliott Hughes "aots/gsub_context2_simple_f1.otf": ("GDEF", "GSUB"), 225*e1fe3e4aSElliott Hughes "aots/gsub_context2_simple_f2.otf": ("GDEF", "GSUB"), 226*e1fe3e4aSElliott Hughes "aots/gsub_context2_successive_f1.otf": ("GDEF", "GSUB"), 227*e1fe3e4aSElliott Hughes "aots/gsub_context3_boundary_f1.otf": ("GDEF", "GSUB"), 228*e1fe3e4aSElliott Hughes "aots/gsub_context3_boundary_f2.otf": ("GDEF", "GSUB"), 229*e1fe3e4aSElliott Hughes "aots/gsub_context3_lookupflag_f1.otf": ("GDEF", "GSUB"), 230*e1fe3e4aSElliott Hughes "aots/gsub_context3_lookupflag_f2.otf": ("GDEF", "GSUB"), 231*e1fe3e4aSElliott Hughes "aots/gsub_context3_next_glyph_f1.otf": ("GDEF", "GSUB"), 232*e1fe3e4aSElliott Hughes "aots/gsub_context3_simple_f1.otf": ("GDEF", "GSUB"), 233*e1fe3e4aSElliott Hughes "aots/gsub_context3_successive_f1.otf": ("GDEF", "GSUB"), 234*e1fe3e4aSElliott Hughes "aots/lookupflag_ignore_attach_f1.otf": ("GDEF", "GSUB"), 235*e1fe3e4aSElliott Hughes "aots/lookupflag_ignore_base_f1.otf": ("GDEF", "GSUB"), 236*e1fe3e4aSElliott Hughes "aots/lookupflag_ignore_combination_f1.otf": ("GDEF", "GSUB"), 237*e1fe3e4aSElliott Hughes "aots/lookupflag_ignore_ligatures_f1.otf": ("GDEF", "GSUB"), 238*e1fe3e4aSElliott Hughes "aots/lookupflag_ignore_marks_f1.otf": ("GDEF", "GSUB"), 239*e1fe3e4aSElliott Hughes "graphite/graphite_tests.ttf": ("Silf", "Glat", "Feat", "Sill"), 240*e1fe3e4aSElliott Hughes} 241*e1fe3e4aSElliott Hughes 242*e1fe3e4aSElliott Hughes 243*e1fe3e4aSElliott HughesTEST_REQUIREMENTS = { 244*e1fe3e4aSElliott Hughes "aots/cmap4_font4.otf": ("unicodedata2",), 245*e1fe3e4aSElliott Hughes} 246*e1fe3e4aSElliott Hughes 247*e1fe3e4aSElliott Hughes 248*e1fe3e4aSElliott HughesttLibVersion_RE = re.compile(r' ttLibVersion=".*"') 249*e1fe3e4aSElliott Hughes 250*e1fe3e4aSElliott Hughes 251*e1fe3e4aSElliott Hughesdef getpath(testfile): 252*e1fe3e4aSElliott Hughes path = os.path.dirname(__file__) 253*e1fe3e4aSElliott Hughes return os.path.join(path, "data", testfile) 254*e1fe3e4aSElliott Hughes 255*e1fe3e4aSElliott Hughes 256*e1fe3e4aSElliott Hughesdef read_expected_ttx(testfile, tableTag): 257*e1fe3e4aSElliott Hughes name = os.path.splitext(testfile)[0] 258*e1fe3e4aSElliott Hughes xml_expected_path = getpath("%s.ttx.%s" % (name, tagToXML(tableTag))) 259*e1fe3e4aSElliott Hughes with open(xml_expected_path, "r", encoding="utf-8") as xml_file: 260*e1fe3e4aSElliott Hughes xml_expected = ttLibVersion_RE.sub("", xml_file.read()) 261*e1fe3e4aSElliott Hughes return xml_expected 262*e1fe3e4aSElliott Hughes 263*e1fe3e4aSElliott Hughes 264*e1fe3e4aSElliott Hughesdef dump_ttx(font, tableTag): 265*e1fe3e4aSElliott Hughes f = StringIO() 266*e1fe3e4aSElliott Hughes font.saveXML(f, tables=[tableTag]) 267*e1fe3e4aSElliott Hughes return ttLibVersion_RE.sub("", f.getvalue()) 268*e1fe3e4aSElliott Hughes 269*e1fe3e4aSElliott Hughes 270*e1fe3e4aSElliott Hughesdef load_ttx(ttx): 271*e1fe3e4aSElliott Hughes f = StringIO() 272*e1fe3e4aSElliott Hughes f.write(ttx) 273*e1fe3e4aSElliott Hughes f.seek(0) 274*e1fe3e4aSElliott Hughes font = TTFont() 275*e1fe3e4aSElliott Hughes font.importXML(f) 276*e1fe3e4aSElliott Hughes return font 277*e1fe3e4aSElliott Hughes 278*e1fe3e4aSElliott Hughes 279*e1fe3e4aSElliott Hughes@contextlib.contextmanager 280*e1fe3e4aSElliott Hughesdef open_font(testfile): 281*e1fe3e4aSElliott Hughes font = TTFont(getpath(testfile)) 282*e1fe3e4aSElliott Hughes try: 283*e1fe3e4aSElliott Hughes yield font 284*e1fe3e4aSElliott Hughes finally: 285*e1fe3e4aSElliott Hughes font.close() 286*e1fe3e4aSElliott Hughes 287*e1fe3e4aSElliott Hughes 288*e1fe3e4aSElliott Hughesdef _skip_if_requirement_missing(testfile): 289*e1fe3e4aSElliott Hughes if testfile in TEST_REQUIREMENTS: 290*e1fe3e4aSElliott Hughes for req in TEST_REQUIREMENTS[testfile]: 291*e1fe3e4aSElliott Hughes if globals()[req] is None: 292*e1fe3e4aSElliott Hughes pytest.skip("%s not installed" % req) 293*e1fe3e4aSElliott Hughes 294*e1fe3e4aSElliott Hughes 295*e1fe3e4aSElliott Hughesdef test_xml_from_binary(testfile, tableTag): 296*e1fe3e4aSElliott Hughes """Check XML from decompiled object.""" 297*e1fe3e4aSElliott Hughes _skip_if_requirement_missing(testfile) 298*e1fe3e4aSElliott Hughes 299*e1fe3e4aSElliott Hughes xml_expected = read_expected_ttx(testfile, tableTag) 300*e1fe3e4aSElliott Hughes 301*e1fe3e4aSElliott Hughes with open_font(testfile) as font: 302*e1fe3e4aSElliott Hughes xml_from_binary = dump_ttx(font, tableTag) 303*e1fe3e4aSElliott Hughes 304*e1fe3e4aSElliott Hughes assert xml_expected == xml_from_binary 305*e1fe3e4aSElliott Hughes 306*e1fe3e4aSElliott Hughes 307*e1fe3e4aSElliott Hughesdef test_xml_from_xml(testfile, tableTag): 308*e1fe3e4aSElliott Hughes """Check XML from object read from XML.""" 309*e1fe3e4aSElliott Hughes _skip_if_requirement_missing(testfile) 310*e1fe3e4aSElliott Hughes 311*e1fe3e4aSElliott Hughes xml_expected = read_expected_ttx(testfile, tableTag) 312*e1fe3e4aSElliott Hughes 313*e1fe3e4aSElliott Hughes font = load_ttx(xml_expected) 314*e1fe3e4aSElliott Hughes name = os.path.splitext(testfile)[0] 315*e1fe3e4aSElliott Hughes setupfile = getpath("%s.ttx.%s.setup" % (name, tagToXML(tableTag))) 316*e1fe3e4aSElliott Hughes if os.path.exists(setupfile): 317*e1fe3e4aSElliott Hughes # import pdb; pdb.set_trace() 318*e1fe3e4aSElliott Hughes font.importXML(setupfile) 319*e1fe3e4aSElliott Hughes xml_from_xml = dump_ttx(font, tableTag) 320*e1fe3e4aSElliott Hughes 321*e1fe3e4aSElliott Hughes assert xml_expected == xml_from_xml 322*e1fe3e4aSElliott Hughes 323*e1fe3e4aSElliott Hughes 324*e1fe3e4aSElliott Hughesdef pytest_generate_tests(metafunc): 325*e1fe3e4aSElliott Hughes # http://doc.pytest.org/en/latest/parametrize.html#basic-pytest-generate-tests-example 326*e1fe3e4aSElliott Hughes fixturenames = metafunc.fixturenames 327*e1fe3e4aSElliott Hughes argnames = ("testfile", "tableTag") 328*e1fe3e4aSElliott Hughes if all(fn in fixturenames for fn in argnames): 329*e1fe3e4aSElliott Hughes argvalues = [ 330*e1fe3e4aSElliott Hughes (testfile, tableTag) 331*e1fe3e4aSElliott Hughes for testfile, tableTags in sorted(TESTS.items()) 332*e1fe3e4aSElliott Hughes for tableTag in tableTags 333*e1fe3e4aSElliott Hughes ] 334*e1fe3e4aSElliott Hughes metafunc.parametrize(argnames, argvalues) 335*e1fe3e4aSElliott Hughes 336*e1fe3e4aSElliott Hughes 337*e1fe3e4aSElliott Hughesif __name__ == "__main__": 338*e1fe3e4aSElliott Hughes sys.exit(pytest.main(sys.argv)) 339