test_names.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. from fontTools.ttLib import TTFont
  2. from fontTools.misc.testTools import getXML
  3. from axisregistry import (
  4. build_name_table,
  5. build_filename,
  6. build_fvar_instances,
  7. build_stat,
  8. build_variations_ps_name,
  9. _fvar_dflts,
  10. _fvar_instance_collisions,
  11. )
  12. import pytest
  13. import os
  14. CWD = os.path.dirname(__file__)
  15. DATA_DIR = os.path.join(CWD, "data")
  16. roboto_flex_fp = os.path.join(
  17. DATA_DIR,
  18. "RobotoFlex[GRAD,XOPQ,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght].ttf",
  19. )
  20. mavenpro_fp = os.path.join(DATA_DIR, "MavenPro-Regular.ttf")
  21. opensans_roman_fp = os.path.join(DATA_DIR, "OpenSans[wdth,wght].ttf")
  22. opensans_italic_fp = os.path.join(DATA_DIR, "OpenSans-Italic[wdth,wght].ttf")
  23. opensans_cond_roman_fp = os.path.join(DATA_DIR, "OpenSansCondensed[wght].ttf")
  24. opensans_cond_italic_fp = os.path.join(DATA_DIR, "OpenSansCondensed-Italic[wght].ttf")
  25. wonky_fp = os.path.join(DATA_DIR, "Wonky[wdth,wght].ttf")
  26. playfair_fp = os.path.join(DATA_DIR, "Playfair[opsz,wdth,wght].ttf")
  27. wavefont_fp = os.path.join(DATA_DIR, "Wavefont[ROND,YALN,wght].ttf")
  28. @pytest.fixture
  29. def static_font():
  30. return TTFont(mavenpro_fp)
  31. def _test_names(ttFont, expected):
  32. name_table = ttFont["name"]
  33. for k, v in expected.items():
  34. record = name_table.getName(*k)
  35. if not record:
  36. assert record == v, f"{k} record is incorrect, expected {v} got {record}"
  37. else:
  38. record_string = record.toUnicode()
  39. assert (
  40. record_string == v
  41. ), f"{k} record is incorrect, expected {v} got {record}"
  42. @pytest.mark.parametrize(
  43. "fp, family_name, style_name, siblings, expected",
  44. [
  45. # Maven Pro Regular
  46. (
  47. mavenpro_fp,
  48. "Maven Pro",
  49. "Regular",
  50. [],
  51. {
  52. (1, 3, 1, 0x409): "Maven Pro",
  53. (2, 3, 1, 0x409): "Regular",
  54. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-Regular",
  55. (4, 3, 1, 0x409): "Maven Pro Regular",
  56. (6, 3, 1, 0x409): "MavenPro-Regular",
  57. (16, 3, 1, 0x409): None,
  58. (17, 3, 1, 0x409): None,
  59. },
  60. ),
  61. # Maven Pro Italic
  62. (
  63. mavenpro_fp,
  64. "Maven Pro",
  65. "Italic",
  66. [],
  67. {
  68. (1, 3, 1, 0x409): "Maven Pro",
  69. (2, 3, 1, 0x409): "Italic",
  70. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-Italic",
  71. (4, 3, 1, 0x409): "Maven Pro Italic",
  72. (6, 3, 1, 0x409): "MavenPro-Italic",
  73. (16, 3, 1, 0x409): None,
  74. (17, 3, 1, 0x409): None,
  75. },
  76. ),
  77. # Maven Pro Bold
  78. (
  79. mavenpro_fp,
  80. "Maven Pro",
  81. "Bold",
  82. [],
  83. {
  84. (1, 3, 1, 0x409): "Maven Pro",
  85. (2, 3, 1, 0x409): "Bold",
  86. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-Bold",
  87. (4, 3, 1, 0x409): "Maven Pro Bold",
  88. (6, 3, 1, 0x409): "MavenPro-Bold",
  89. (16, 3, 1, 0x409): None,
  90. (17, 3, 1, 0x409): None,
  91. },
  92. ),
  93. # Maven Pro Bold Italic
  94. (
  95. mavenpro_fp,
  96. "Maven Pro",
  97. "Bold Italic",
  98. [],
  99. {
  100. (1, 3, 1, 0x409): "Maven Pro",
  101. (2, 3, 1, 0x409): "Bold Italic",
  102. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-BoldItalic",
  103. (4, 3, 1, 0x409): "Maven Pro Bold Italic",
  104. (6, 3, 1, 0x409): "MavenPro-BoldItalic",
  105. (16, 3, 1, 0x409): None,
  106. (17, 3, 1, 0x409): None,
  107. },
  108. ),
  109. # Maven Pro Black
  110. (
  111. mavenpro_fp,
  112. "Maven Pro",
  113. "Black",
  114. [],
  115. {
  116. (1, 3, 1, 0x409): "Maven Pro Black",
  117. (2, 3, 1, 0x409): "Regular",
  118. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-Black",
  119. (4, 3, 1, 0x409): "Maven Pro Black",
  120. (6, 3, 1, 0x409): "MavenPro-Black",
  121. (16, 3, 1, 0x409): "Maven Pro",
  122. (17, 3, 1, 0x409): "Black",
  123. },
  124. ),
  125. # Maven Pro Black Italic
  126. (
  127. mavenpro_fp,
  128. "Maven Pro",
  129. "Black Italic",
  130. [],
  131. {
  132. (1, 3, 1, 0x409): "Maven Pro Black",
  133. (2, 3, 1, 0x409): "Italic",
  134. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-BlackItalic",
  135. (4, 3, 1, 0x409): "Maven Pro Black Italic",
  136. (6, 3, 1, 0x409): "MavenPro-BlackItalic",
  137. (16, 3, 1, 0x409): "Maven Pro",
  138. (17, 3, 1, 0x409): "Black Italic",
  139. },
  140. ),
  141. # Maven Pro ExtraLight Italic
  142. (
  143. mavenpro_fp,
  144. "Maven Pro",
  145. "ExtraLight Italic",
  146. [],
  147. {
  148. (1, 3, 1, 0x409): "Maven Pro ExtraLight",
  149. (2, 3, 1, 0x409): "Italic",
  150. (3, 3, 1, 0x409): "2.003;NONE;MavenPro-ExtraLightItalic",
  151. (4, 3, 1, 0x409): "Maven Pro ExtraLight Italic",
  152. (6, 3, 1, 0x409): "MavenPro-ExtraLightItalic",
  153. (16, 3, 1, 0x409): "Maven Pro",
  154. (17, 3, 1, 0x409): "ExtraLight Italic",
  155. },
  156. ),
  157. # check non-weight styles get appended to family name
  158. # Maven Pro UltraExpanded Regular
  159. (
  160. mavenpro_fp,
  161. "Maven Pro",
  162. "UltraExpanded Regular",
  163. [],
  164. {
  165. (1, 3, 1, 0x409): "Maven Pro UltraExpanded",
  166. (2, 3, 1, 0x409): "Regular",
  167. (3, 3, 1, 0x409): "2.003;NONE;MavenProUltraExpanded-Regular",
  168. (4, 3, 1, 0x409): "Maven Pro UltraExpanded Regular",
  169. (6, 3, 1, 0x409): "MavenProUltraExpanded-Regular",
  170. (16, 3, 1, 0x409): None,
  171. (17, 3, 1, 0x409): None,
  172. },
  173. ),
  174. # Maven Pro Condensed ExtraLight Italic
  175. (
  176. mavenpro_fp,
  177. "Maven Pro",
  178. "Condensed ExtraLight Italic",
  179. [],
  180. {
  181. (1, 3, 1, 0x409): "Maven Pro Condensed ExtraLight",
  182. (2, 3, 1, 0x409): "Italic",
  183. (3, 3, 1, 0x409): "2.003;NONE;MavenProCondensed-ExtraLightItalic",
  184. (4, 3, 1, 0x409): "Maven Pro Condensed ExtraLight Italic",
  185. (6, 3, 1, 0x409): "MavenProCondensed-ExtraLightItalic",
  186. (16, 3, 1, 0x409): "Maven Pro Condensed",
  187. (17, 3, 1, 0x409): "ExtraLight Italic",
  188. },
  189. ),
  190. ## VFs
  191. # Open Sans Roman
  192. (
  193. opensans_roman_fp,
  194. "Open Sans",
  195. None,
  196. [opensans_italic_fp, opensans_cond_roman_fp, opensans_cond_italic_fp],
  197. {
  198. (1, 3, 1, 0x409): "Open Sans",
  199. (2, 3, 1, 0x409): "Regular",
  200. (3, 3, 1, 0x409): "3.000;GOOG;OpenSans-Regular",
  201. (4, 3, 1, 0x409): "Open Sans Regular",
  202. (6, 3, 1, 0x409): "OpenSans-Regular",
  203. (16, 3, 1, 0x409): None,
  204. (17, 3, 1, 0x409): None,
  205. (25, 3, 1, 0x409): "OpenSans",
  206. },
  207. ),
  208. # Open Sans Italic
  209. (
  210. opensans_italic_fp,
  211. "Open Sans",
  212. None,
  213. [opensans_roman_fp, opensans_cond_roman_fp, opensans_cond_italic_fp],
  214. {
  215. (1, 3, 1, 0x409): "Open Sans",
  216. (2, 3, 1, 0x409): "Italic",
  217. (3, 3, 1, 0x409): "3.000;GOOG;OpenSans-Italic",
  218. (4, 3, 1, 0x409): "Open Sans Italic",
  219. (6, 3, 1, 0x409): "OpenSans-Italic",
  220. (16, 3, 1, 0x409): None,
  221. (17, 3, 1, 0x409): None,
  222. (25, 3, 1, 0x409): "OpenSansItalic",
  223. },
  224. ),
  225. # Open Sans Cond Roman
  226. (
  227. opensans_cond_roman_fp,
  228. "Open Sans Condensed",
  229. None,
  230. [opensans_roman_fp, opensans_italic_fp, opensans_cond_italic_fp],
  231. {
  232. (1, 3, 1, 0x409): "Open Sans Condensed",
  233. (2, 3, 1, 0x409): "Regular",
  234. (3, 3, 1, 0x409): "3.000;GOOG;OpenSansCondensed-Regular",
  235. (4, 3, 1, 0x409): "Open Sans Condensed Regular",
  236. (6, 3, 1, 0x409): "OpenSansCondensed-Regular",
  237. (16, 3, 1, 0x409): None,
  238. (17, 3, 1, 0x409): None,
  239. (25, 3, 1, 0x409): "OpenSansCondensed",
  240. },
  241. ),
  242. # Open Sans Cond Italic
  243. (
  244. opensans_cond_italic_fp,
  245. "Open Sans Condensed",
  246. None,
  247. [opensans_roman_fp, opensans_italic_fp, opensans_cond_roman_fp],
  248. {
  249. (1, 3, 1, 0x409): "Open Sans Condensed",
  250. (2, 3, 1, 0x409): "Italic",
  251. (3, 3, 1, 0x409): "3.000;GOOG;OpenSansCondensed-Italic",
  252. (4, 3, 1, 0x409): "Open Sans Condensed Italic",
  253. (6, 3, 1, 0x409): "OpenSansCondensed-Italic",
  254. (16, 3, 1, 0x409): None,
  255. (17, 3, 1, 0x409): None,
  256. (25, 3, 1, 0x409): "OpenSansCondensedItalic",
  257. },
  258. ),
  259. # Bad names
  260. (
  261. mavenpro_fp,
  262. "Maven Pro",
  263. "Fat", # this should get appended to the family name
  264. [],
  265. {
  266. (1, 3, 1, 0x409): "Maven Pro Fat",
  267. (2, 3, 1, 0x409): "Regular",
  268. (3, 3, 1, 0x409): "2.003;NONE;MavenProFat-Regular",
  269. (4, 3, 1, 0x409): "Maven Pro Fat Regular",
  270. (6, 3, 1, 0x409): "MavenProFat-Regular",
  271. (16, 3, 1, 0x409): None,
  272. (17, 3, 1, 0x409): None,
  273. },
  274. ),
  275. (
  276. wonky_fp,
  277. "Wonky", # name exists in axis reg!
  278. None,
  279. [],
  280. {
  281. (1, 3, 1, 0x409): "Wonky",
  282. (2, 3, 1, 0x409): "Regular",
  283. (3, 3, 1, 0x409): "3.000;GOOG;Wonky-Regular",
  284. (4, 3, 1, 0x409): "Wonky Regular",
  285. (6, 3, 1, 0x409): "Wonky-Regular",
  286. (16, 3, 1, 0x409): None,
  287. (17, 3, 1, 0x409): None,
  288. },
  289. ),
  290. # Test opsz particle is kept.
  291. # Fixes https://github.com/googlefonts/axisregistry/issues/130
  292. (
  293. playfair_fp,
  294. "Playfair",
  295. None,
  296. [],
  297. {
  298. (1, 3, 1, 0x409): "Playfair SemiExpanded Light",
  299. (2, 3, 1, 0x409): "Regular",
  300. (3, 3, 1, 0x409): "2.000;FTH;Playfair-SemiExpandedLight",
  301. (4, 3, 1, 0x409): "Playfair SemiExpanded Light",
  302. (6, 3, 1, 0x409): "Playfair-SemiExpandedLight",
  303. (16, 3, 1, 0x409): "Playfair",
  304. (17, 3, 1, 0x409): "SemiExpanded Light",
  305. },
  306. ),
  307. ],
  308. )
  309. def test_name_table(fp, family_name, style_name, siblings, expected):
  310. font = TTFont(fp)
  311. siblings = [TTFont(fp) for fp in siblings]
  312. build_name_table(font, family_name, style_name, siblings)
  313. _test_names(font, expected)
  314. def test_name_table_aggression():
  315. font = TTFont(mavenpro_fp)
  316. build_name_table(font, "Raven Am", "Regular", aggressive=True)
  317. _test_names(
  318. font,
  319. {
  320. (
  321. 0,
  322. 3,
  323. 1,
  324. 0x409,
  325. ): 'Copyright 2011 The Raven Am Project Authors (http://www.vissol.co.uk/mavenpro/), with Reserved Font Name "Raven Am".',
  326. (4, 3, 1, 0x409): "Raven Am Regular",
  327. },
  328. )
  329. font = TTFont(mavenpro_fp)
  330. build_name_table(font, "Raven Am", "Regular", aggressive=False)
  331. _test_names(
  332. font,
  333. {
  334. (
  335. 0,
  336. 3,
  337. 1,
  338. 0x409,
  339. ): 'Copyright 2011 The Maven Pro Project Authors (http://www.vissol.co.uk/mavenpro/), with Reserved Font Name "Maven Pro".',
  340. (4, 3, 1, 0x409): "Raven Am Regular",
  341. },
  342. )
  343. @pytest.mark.parametrize(
  344. "font_fp, dflt_coords, expected",
  345. [
  346. # Condensed variants
  347. (
  348. opensans_cond_roman_fp,
  349. {},
  350. [
  351. ("Thin", {"wght": 100.0}),
  352. ("ExtraLight", {"wght": 200.0}),
  353. ("Light", {"wght": 300.0}),
  354. ("Regular", {"wght": 400.0}),
  355. ("Medium", {"wght": 500.0}),
  356. ("SemiBold", {"wght": 600.0}),
  357. ("Bold", {"wght": 700.0}),
  358. ("ExtraBold", {"wght": 800.0}),
  359. ],
  360. ),
  361. (
  362. opensans_cond_italic_fp,
  363. {},
  364. [
  365. ("Thin Italic", {"wght": 100.0}),
  366. ("ExtraLight Italic", {"wght": 200.0}),
  367. ("Light Italic", {"wght": 300.0}),
  368. ("Italic", {"wght": 400.0}),
  369. ("Medium Italic", {"wght": 500.0}),
  370. ("SemiBold Italic", {"wght": 600.0}),
  371. ("Bold Italic", {"wght": 700.0}),
  372. ("ExtraBold Italic", {"wght": 800.0}),
  373. ],
  374. ),
  375. # Multi axis + roman & ital with dflt coords
  376. (
  377. roboto_flex_fp,
  378. {},
  379. [
  380. ("Thin", {"wght": 100.0}),
  381. ("ExtraLight", {"wght": 200.0}),
  382. ("Light", {"wght": 300.0}),
  383. ("Regular", {"wght": 400.0}),
  384. ("Medium", {"wght": 500.0}),
  385. ("SemiBold", {"wght": 600.0}),
  386. ("Bold", {"wght": 700.0}),
  387. ("ExtraBold", {"wght": 800.0}),
  388. ("Black", {"wght": 900.0}),
  389. ("Thin Italic", {"wght": 100.0, "slnt": -10}),
  390. ("ExtraLight Italic", {"wght": 200.0, "slnt": -10}),
  391. ("Light Italic", {"wght": 300.0, "slnt": -10}),
  392. ("Italic", {"wght": 400.0, "slnt": -10}),
  393. ("Medium Italic", {"wght": 500.0, "slnt": -10}),
  394. ("SemiBold Italic", {"wght": 600.0, "slnt": -10}),
  395. ("Bold Italic", {"wght": 700.0, "slnt": -10}),
  396. ("ExtraBold Italic", {"wght": 800.0, "slnt": -10}),
  397. ("Black Italic", {"wght": 900.0, "slnt": -10}),
  398. ],
  399. ),
  400. # multi axis with METADATA.pb registry_default_overrides
  401. # https://github.com/google/fonts/blob/main/ofl/robotoflex/METADATA.pb
  402. (
  403. roboto_flex_fp,
  404. {
  405. "XOPQ": 96.0,
  406. "XTRA": 468.0,
  407. "YOPQ": 79.0,
  408. "YTDE": -203.0,
  409. "YTFI": 738.0,
  410. "YTLC": 514.0,
  411. "YTUC": 712.0,
  412. },
  413. [
  414. ("Thin", {"wght": 100.0}),
  415. ("ExtraLight", {"wght": 200.0}),
  416. ("Light", {"wght": 300.0}),
  417. ("Regular", {"wght": 400.0}),
  418. ("Medium", {"wght": 500.0}),
  419. ("SemiBold", {"wght": 600.0}),
  420. ("Bold", {"wght": 700.0}),
  421. ("ExtraBold", {"wght": 800.0}),
  422. ("Black", {"wght": 900.0}),
  423. ("Thin Italic", {"wght": 100.0, "slnt": -10}),
  424. ("ExtraLight Italic", {"wght": 200.0, "slnt": -10}),
  425. ("Light Italic", {"wght": 300.0, "slnt": -10}),
  426. ("Italic", {"wght": 400.0, "slnt": -10}),
  427. ("Medium Italic", {"wght": 500.0, "slnt": -10}),
  428. ("SemiBold Italic", {"wght": 600.0, "slnt": -10}),
  429. ("Bold Italic", {"wght": 700.0, "slnt": -10}),
  430. ("ExtraBold Italic", {"wght": 800.0, "slnt": -10}),
  431. ("Black Italic", {"wght": 900.0, "slnt": -10}),
  432. ],
  433. ),
  434. ],
  435. )
  436. def test_fvar_instances(font_fp, dflt_coords, expected):
  437. font = TTFont(font_fp)
  438. builder = build_fvar_instances(font, dflt_coords)
  439. fvar = font["fvar"]
  440. wght_axis = next((a for a in fvar.axes if a.axisTag == "wght"), None)
  441. wght_min = wght_axis.minValue
  442. wght_max = wght_axis.maxValue
  443. instances = fvar.instances
  444. if not dflt_coords:
  445. dflt_coords = {k: v["value"] for k, v in _fvar_dflts(font).items()}
  446. assert len(instances) == len(expected)
  447. for inst, (expected_name, coords) in zip(instances, expected):
  448. inst_name = font["name"].getName(inst.subfamilyNameID, 3, 1, 0x409).toUnicode()
  449. assert inst_name == expected_name
  450. for tag, val in coords.items():
  451. dflt_coords[tag] = val
  452. assert inst.coordinates == dflt_coords
  453. def dump(table, ttFont=None):
  454. return "\n".join(getXML(table.toXML, ttFont))
  455. @pytest.mark.parametrize(
  456. "fp, sibling_fps",
  457. [
  458. (roboto_flex_fp, []),
  459. (
  460. opensans_roman_fp,
  461. [opensans_italic_fp, opensans_cond_roman_fp, opensans_cond_italic_fp],
  462. ),
  463. (
  464. opensans_italic_fp,
  465. [opensans_roman_fp, opensans_cond_roman_fp, opensans_cond_italic_fp],
  466. ),
  467. (
  468. opensans_cond_roman_fp,
  469. [opensans_roman_fp, opensans_italic_fp, opensans_cond_italic_fp],
  470. ),
  471. (
  472. opensans_cond_italic_fp,
  473. [opensans_roman_fp, opensans_italic_fp, opensans_cond_roman_fp],
  474. ),
  475. (wonky_fp, []),
  476. # don't add a linkedValue for Regular to Bold since Bold doesn't exist
  477. # Fixes https://github.com/googlefonts/axisregistry/issues/104
  478. (wavefont_fp, []),
  479. ],
  480. )
  481. def test_stat(fp, sibling_fps):
  482. font = TTFont(fp)
  483. siblings = [TTFont(f) for f in sibling_fps]
  484. build_stat(font, siblings)
  485. stat_fp = fp.replace(".ttf", "_STAT.ttx")
  486. ## output good files
  487. # with open(stat_fp, "w") as doc:
  488. # got = dump(font["STAT"], font)
  489. # doc.write(got)
  490. with open(stat_fp) as doc:
  491. expected = doc.read()
  492. got = dump(font["STAT"], font)
  493. assert got == expected
  494. @pytest.mark.parametrize(
  495. "fp, expected",
  496. [
  497. (mavenpro_fp, "MavenPro-Regular.ttf"),
  498. (opensans_roman_fp, "OpenSans[wdth,wght].ttf"),
  499. (opensans_italic_fp, "OpenSans-Italic[wdth,wght].ttf"),
  500. (opensans_cond_roman_fp, "OpenSansCondensed[wght].ttf"),
  501. (opensans_cond_italic_fp, "OpenSansCondensed-Italic[wght].ttf"),
  502. ],
  503. )
  504. def test_filename(fp, expected):
  505. font = TTFont(fp)
  506. assert build_filename(font) == expected
  507. @pytest.mark.parametrize(
  508. "fp, sibling_fps, result",
  509. [
  510. (roboto_flex_fp, [], False),
  511. (
  512. opensans_roman_fp,
  513. [opensans_italic_fp, opensans_cond_roman_fp, opensans_cond_italic_fp],
  514. True,
  515. ),
  516. (
  517. opensans_italic_fp,
  518. [opensans_roman_fp, opensans_cond_roman_fp, opensans_cond_italic_fp],
  519. True,
  520. ),
  521. (
  522. opensans_cond_roman_fp,
  523. [opensans_roman_fp, opensans_italic_fp, opensans_cond_italic_fp],
  524. True,
  525. ),
  526. (
  527. opensans_cond_italic_fp,
  528. [opensans_roman_fp, opensans_italic_fp, opensans_cond_roman_fp],
  529. True,
  530. ),
  531. (opensans_roman_fp, [opensans_cond_roman_fp], True),
  532. (opensans_roman_fp, [opensans_italic_fp], False),
  533. (wonky_fp, [], False),
  534. ],
  535. )
  536. def test_fvar_instance_collisions(fp, sibling_fps, result):
  537. ttFont = TTFont(fp)
  538. siblings = [TTFont(fp) for fp in sibling_fps]
  539. assert _fvar_instance_collisions(ttFont, siblings) == result
  540. @pytest.mark.parametrize(
  541. "fp, result",
  542. [
  543. (roboto_flex_fp, "RobotoFlex"),
  544. (opensans_roman_fp, "OpenSans"),
  545. (opensans_italic_fp, "OpenSansItalic"),
  546. (opensans_cond_roman_fp, "OpenSansCondensed"),
  547. (opensans_cond_italic_fp, "OpenSansCondensedItalic"),
  548. (wonky_fp, "Wonky"),
  549. ],
  550. )
  551. def test_build_variations_ps_name(fp, result):
  552. ttFont = TTFont(fp)
  553. build_variations_ps_name(ttFont)
  554. variation_ps_name = ttFont["name"].getName(25, 3, 1, 0x409).toUnicode()
  555. assert variation_ps_name == result
  556. @pytest.mark.parametrize(
  557. "fp, style_name, result",
  558. [
  559. (mavenpro_fp, "Regular", 400),
  560. (mavenpro_fp, "Italic", 400),
  561. (mavenpro_fp, "Black Italic", 900),
  562. (mavenpro_fp, "ExtraBold Italic", 800),
  563. (mavenpro_fp, "ExtraBold", 800),
  564. (mavenpro_fp, "Bold", 700),
  565. (mavenpro_fp, "Bold Italic", 700),
  566. (mavenpro_fp, "Thin Italic", 100),
  567. (mavenpro_fp, "Thin", 100),
  568. ],
  569. )
  570. def test_us_weight_class(fp, style_name, result):
  571. ttFont = TTFont(fp)
  572. build_name_table(ttFont, style_name=style_name)
  573. assert ttFont["OS/2"].usWeightClass == result