test_ft2font.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from pathlib import Path
  2. import io
  3. import pytest
  4. from matplotlib import ft2font
  5. from matplotlib.testing.decorators import check_figures_equal
  6. import matplotlib.font_manager as fm
  7. import matplotlib.pyplot as plt
  8. def test_fallback_errors():
  9. file_name = fm.findfont('DejaVu Sans')
  10. with pytest.raises(TypeError, match="Fallback list must be a list"):
  11. # failing to be a list will fail before the 0
  12. ft2font.FT2Font(file_name, _fallback_list=(0,)) # type: ignore[arg-type]
  13. with pytest.raises(
  14. TypeError, match="Fallback fonts must be FT2Font objects."
  15. ):
  16. ft2font.FT2Font(file_name, _fallback_list=[0]) # type: ignore[list-item]
  17. def test_ft2font_positive_hinting_factor():
  18. file_name = fm.findfont('DejaVu Sans')
  19. with pytest.raises(
  20. ValueError, match="hinting_factor must be greater than 0"
  21. ):
  22. ft2font.FT2Font(file_name, 0)
  23. def test_fallback_smoke():
  24. fp = fm.FontProperties(family=["WenQuanYi Zen Hei"])
  25. if Path(fm.findfont(fp)).name != "wqy-zenhei.ttc":
  26. pytest.skip("Font wqy-zenhei.ttc may be missing")
  27. fp = fm.FontProperties(family=["Noto Sans CJK JP"])
  28. if Path(fm.findfont(fp)).name != "NotoSansCJK-Regular.ttc":
  29. pytest.skip("Noto Sans CJK JP font may be missing.")
  30. plt.rcParams['font.size'] = 20
  31. fig = plt.figure(figsize=(4.75, 1.85))
  32. fig.text(0.05, 0.45, "There are 几个汉字 in between!",
  33. family=['DejaVu Sans', "Noto Sans CJK JP"])
  34. fig.text(0.05, 0.25, "There are 几个汉字 in between!",
  35. family=['DejaVu Sans', "WenQuanYi Zen Hei"])
  36. fig.text(0.05, 0.65, "There are 几个汉字 in between!",
  37. family=["Noto Sans CJK JP"])
  38. fig.text(0.05, 0.85, "There are 几个汉字 in between!",
  39. family=["WenQuanYi Zen Hei"])
  40. # TODO enable fallback for other backends!
  41. for fmt in ['png', 'raw']: # ["svg", "pdf", "ps"]:
  42. fig.savefig(io.BytesIO(), format=fmt)
  43. @pytest.mark.parametrize('family_name, file_name',
  44. [("WenQuanYi Zen Hei", "wqy-zenhei"),
  45. ("Noto Sans CJK JP", "NotoSansCJK")]
  46. )
  47. @check_figures_equal(extensions=["png", "pdf", "eps", "svg"])
  48. def test_font_fallback_chinese(fig_test, fig_ref, family_name, file_name):
  49. fp = fm.FontProperties(family=[family_name])
  50. if file_name not in Path(fm.findfont(fp)).name:
  51. pytest.skip(f"Font {family_name} ({file_name}) is missing")
  52. text = ["There are", "几个汉字", "in between!"]
  53. plt.rcParams["font.size"] = 20
  54. test_fonts = [["DejaVu Sans", family_name]] * 3
  55. ref_fonts = [["DejaVu Sans"], [family_name], ["DejaVu Sans"]]
  56. for j, (txt, test_font, ref_font) in enumerate(
  57. zip(text, test_fonts, ref_fonts)
  58. ):
  59. fig_ref.text(0.05, .85 - 0.15*j, txt, family=ref_font)
  60. fig_test.text(0.05, .85 - 0.15*j, txt, family=test_font)
  61. @pytest.mark.parametrize(
  62. "family_name, file_name",
  63. [
  64. ("WenQuanYi Zen Hei", "wqy-zenhei"),
  65. ("Noto Sans CJK JP", "NotoSansCJK"),
  66. ],
  67. )
  68. def test__get_fontmap(family_name, file_name):
  69. fp = fm.FontProperties(family=[family_name])
  70. found_file_name = Path(fm.findfont(fp)).name
  71. if file_name not in found_file_name:
  72. pytest.skip(f"Font {family_name} ({file_name}) is missing")
  73. text = "There are 几个汉字 in between!"
  74. ft = fm.get_font(
  75. fm.fontManager._find_fonts_by_props(
  76. fm.FontProperties(family=["DejaVu Sans", family_name])
  77. )
  78. )
  79. fontmap = ft._get_fontmap(text)
  80. for char, font in fontmap.items():
  81. if ord(char) > 127:
  82. assert Path(font.fname).name == found_file_name
  83. else:
  84. assert Path(font.fname).name == "DejaVuSans.ttf"