interpolatableTestContourOrder.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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 a 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. if not done:
  42. m1ControlReversed = [(-m[0],) + m[1:] for m in m1Control]
  43. (
  44. matching_control_reversed,
  45. matching_cost_control_reversed,
  46. identity_cost_control_reversed,
  47. ) = matching_for_vectors(m0Control, m1ControlReversed)
  48. done = matching_cost_control_reversed == identity_cost_control_reversed
  49. if not done:
  50. m1GreenReversed = [(-m[0],) + m[1:] for m in m1Green]
  51. (
  52. matching_control_reversed,
  53. matching_cost_green_reversed,
  54. identity_cost_green_reversed,
  55. ) = matching_for_vectors(m0Green, m1GreenReversed)
  56. done = matching_cost_green_reversed == identity_cost_green_reversed
  57. if not done:
  58. # Otherwise, use the worst of the two matchings.
  59. if (
  60. matching_cost_control / identity_cost_control
  61. < matching_cost_green / identity_cost_green
  62. ):
  63. matching = matching_control
  64. matching_cost = matching_cost_control
  65. identity_cost = identity_cost_control
  66. else:
  67. matching = matching_green
  68. matching_cost = matching_cost_green
  69. identity_cost = identity_cost_green
  70. this_tolerance = matching_cost / identity_cost if identity_cost else 1
  71. log.debug(
  72. "test-contour-order: tolerance %g",
  73. this_tolerance,
  74. )
  75. return this_tolerance, matching