interpolatableTestContourOrder.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from .interpolatableHelpers import *
  2. import logging
  3. log = logging.getLogger("fontTools.varLib.interpolatable")
  4. def test_contour_order(glyph0, glyph1):
  5. # We try matching both the StatisticsControlPen vector
  6. # and the StatisticsPen vector.
  7. #
  8. # If either method found an identity matching, accept it.
  9. # This is crucial for fonts like Kablammo[MORF].ttf and
  10. # Nabla[EDPT,EHLT].ttf, since they really confuse the
  11. # StatisticsPen vector because of their area=0 contours.
  12. n = len(glyph0.controlVectors)
  13. matching = None
  14. matching_cost = 0
  15. identity_cost = 0
  16. done = n <= 1
  17. if not done:
  18. m0Control = glyph0.controlVectors
  19. m1Control = glyph1.controlVectors
  20. (
  21. matching_control,
  22. matching_cost_control,
  23. identity_cost_control,
  24. ) = matching_for_vectors(m0Control, m1Control)
  25. done = matching_cost_control == identity_cost_control
  26. if not done:
  27. m0Green = glyph0.greenVectors
  28. m1Green = glyph1.greenVectors
  29. (
  30. matching_green,
  31. matching_cost_green,
  32. identity_cost_green,
  33. ) = matching_for_vectors(m0Green, m1Green)
  34. done = matching_cost_green == identity_cost_green
  35. if not done:
  36. # See if reversing contours in one master helps.
  37. # That's a common problem. Then the wrong_start_point
  38. # test will fix them.
  39. #
  40. # Reverse the sign of the area (0); the rest stay the same.
  41. m1ControlReversed = [(-m[0],) + m[1:] for m in m1Control]
  42. (
  43. matching_control_reversed,
  44. matching_cost_control_reversed,
  45. identity_cost_control_reversed,
  46. ) = matching_for_vectors(m0Control, m1ControlReversed)
  47. done = matching_cost_control_reversed == identity_cost_control_reversed
  48. if not done:
  49. m1GreenReversed = [(-m[0],) + m[1:] for m in m1Green]
  50. (
  51. matching_green_reversed,
  52. matching_cost_green_reversed,
  53. identity_cost_green_reversed,
  54. ) = matching_for_vectors(m0Green, m1GreenReversed)
  55. done = matching_cost_green_reversed == identity_cost_green_reversed
  56. if not done:
  57. # Otherwise, use the best of the two matchings.
  58. if (
  59. matching_cost_control * identity_cost_green
  60. < matching_cost_green * identity_cost_control
  61. ):
  62. matching = matching_control
  63. matching_cost = matching_cost_control
  64. identity_cost = identity_cost_control
  65. else:
  66. matching = matching_green
  67. matching_cost = matching_cost_green
  68. identity_cost = identity_cost_green
  69. this_tolerance = matching_cost / identity_cost if identity_cost else 1
  70. log.debug(
  71. "test-contour-order: tolerance %g",
  72. this_tolerance,
  73. )
  74. return this_tolerance, matching