Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

104 wiersze
4.2KB

  1. using EnvelopeRenderer.Cli.Render;
  2. namespace EnvelopeRenderer.Cli.Tests;
  3. public class RotatedTextAnchorCalculatorTests
  4. {
  5. [Fact]
  6. public void ComputeAnchor_ZeroAngle_ReturnsOriginalAnchorUnchanged()
  7. {
  8. var (x, y) = RotatedTextAnchorCalculator.ComputeAnchor(
  9. x: 120, y: 240, width: 50, ascent: 10, descent: -3, angleDegrees: 0);
  10. Assert.Equal(120, x, precision: 9);
  11. Assert.Equal(240, y, precision: 9);
  12. }
  13. [Fact]
  14. public void ComputeAnchor_180Degrees_ReflectsAnchorThroughBoundingBoxCenter()
  15. {
  16. // A 180-degree rotation about a fixed center C maps any point P to 2C - P. Applying that
  17. // to the anchor itself: the corrected anchor should be exactly the bbox center reflected
  18. // through itself minus... concretely: center = (x + width/2, y + (ascent+descent)/2);
  19. // for a 180-degree rotation, anchor' = 2*center - (x, y).
  20. const double x = 100;
  21. const double y = 100;
  22. const double width = 40;
  23. const double ascent = 20;
  24. const double descent = -4;
  25. var centerX = x + (width / 2.0);
  26. var centerY = y + ((ascent + descent) / 2.0);
  27. var (anchorX, anchorY) = RotatedTextAnchorCalculator.ComputeAnchor(x, y, width, ascent, descent, 180);
  28. Assert.Equal((2 * centerX) - x, anchorX, precision: 6);
  29. Assert.Equal((2 * centerY) - y, anchorY, precision: 6);
  30. }
  31. [Fact]
  32. public void ComputeAnchor_90Degrees_MatchesHandDerivedCounterclockwiseFormula()
  33. {
  34. // Confirmed empirically against the real Debenu DLL (see RotatedTextAnchorCalculator's
  35. // class remarks): positive angle is counterclockwise in PDF's Y-up space, i.e. the
  36. // standard math rotation matrix applied directly with no sign flip.
  37. const double x = 0;
  38. const double y = 0;
  39. const double width = 10; // centerLocal = (5, 5)
  40. const double ascent = 12;
  41. const double descent = -2; // (ascent+descent)/2 = 5
  42. var (anchorX, anchorY) = RotatedTextAnchorCalculator.ComputeAnchor(x, y, width, ascent, descent, 90);
  43. // R(90) * (5,5) = (5*cos90 - 5*sin90, 5*sin90 + 5*cos90) = (-5, 5).
  44. // anchor' = (x,y) + centerLocal - R(90)*centerLocal = (0,0) + (5,5) - (-5,5) = (10, 0).
  45. Assert.Equal(10, anchorX, precision: 6);
  46. Assert.Equal(0, anchorY, precision: 6);
  47. }
  48. [Fact]
  49. public void ComputeAnchor_NegativeAngle_RotatesTheOppositeDirection()
  50. {
  51. var (positiveX, positiveY) = RotatedTextAnchorCalculator.ComputeAnchor(50, 50, 30, 15, -3, 40);
  52. var (negativeX, negativeY) = RotatedTextAnchorCalculator.ComputeAnchor(50, 50, 30, 15, -3, -40);
  53. Assert.NotEqual(positiveX, negativeX, precision: 3);
  54. Assert.NotEqual(positiveY, negativeY, precision: 3);
  55. }
  56. [Theory]
  57. [InlineData(30)]
  58. [InlineData(90)]
  59. [InlineData(180)]
  60. [InlineData(-45)]
  61. [InlineData(270)]
  62. public void ComputeAnchor_AnyAngle_PreservesTheUnrotatedBoundingBoxCenter(double angle)
  63. {
  64. // The whole point of this calculator: regardless of angle, the resulting anchor, once
  65. // Debenu rotates its local bbox center around it by `angle`, lands back on the *original*
  66. // (unrotated) bbox center. Verify that directly by applying the same rotation formula
  67. // DrawRotatedText uses (confirmed CCW-positive) to the anchor's own local center offset.
  68. const double x = 77;
  69. const double y = 33;
  70. const double width = 64;
  71. const double ascent = 18;
  72. const double descent = -6;
  73. var centerLocalX = width / 2.0;
  74. var centerLocalY = (ascent + descent) / 2.0;
  75. var expectedCenterX = x + centerLocalX;
  76. var expectedCenterY = y + centerLocalY;
  77. var (anchorX, anchorY) = RotatedTextAnchorCalculator.ComputeAnchor(x, y, width, ascent, descent, angle);
  78. var radians = angle * Math.PI / 180.0;
  79. var cos = Math.Cos(radians);
  80. var sin = Math.Sin(radians);
  81. var rotatedCenterX = anchorX + ((centerLocalX * cos) - (centerLocalY * sin));
  82. var rotatedCenterY = anchorY + ((centerLocalX * sin) + (centerLocalY * cos));
  83. Assert.Equal(expectedCenterX, rotatedCenterX, precision: 6);
  84. Assert.Equal(expectedCenterY, rotatedCenterY, precision: 6);
  85. }
  86. }

Powered by TurnKey Linux.