LayoutTestExecutor.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using QuestPDF.Drawing;
  2. using QuestPDF.Drawing.Proxy;
  3. using QuestPDF.Elements;
  4. using QuestPDF.Helpers;
  5. using QuestPDF.Infrastructure;
  6. namespace QuestPDF.LayoutTests.TestEngine;
  7. internal static class LayoutTestExecutor
  8. {
  9. public static LayoutTestResult.DocumentLayout Execute(Size pageSize, Container container)
  10. {
  11. var (pageSizes, generatesInfiniteLayout) = GenerateDocument();
  12. container.ReleaseDisposableChildren();
  13. return new LayoutTestResult.DocumentLayout
  14. {
  15. Pages = CollectMockInformation(pageSizes),
  16. GeneratesInfiniteLayout = generatesInfiniteLayout
  17. };
  18. (List<Size> pageSizes, bool generatesInfiniteLayout) GenerateDocument()
  19. {
  20. // inject dependencies
  21. var pageContext = new PageContext();
  22. pageContext.ProceedToNextRenderingPhase();
  23. using var canvas = new CompanionCanvas();
  24. container.InjectDependencies(pageContext, canvas);
  25. // distribute global state
  26. container.ApplyInheritedAndGlobalTexStyle(TextStyle.Default);
  27. container.ApplyContentDirection(ContentDirection.LeftToRight);
  28. container.ApplyDefaultImageConfiguration(DocumentSettings.Default.ImageRasterDpi, DocumentSettings.Default.ImageCompressionQuality, true);
  29. // render
  30. container.VisitChildren(x => (x as IStateful)?.ResetState());
  31. canvas.BeginDocument();
  32. var pageSizes = new List<Size>();
  33. while(true)
  34. {
  35. pageContext.IncrementPageNumber();
  36. var spacePlan = container.Measure(pageSize);
  37. pageSizes.Add(spacePlan);
  38. if (spacePlan.Type == SpacePlanType.Wrap)
  39. {
  40. pageContext.DecrementPageNumber();
  41. canvas.EndDocument();
  42. return (pageSizes, true);
  43. }
  44. try
  45. {
  46. canvas.BeginPage(pageSize);
  47. container.Draw(pageSize);
  48. }
  49. catch (Exception exception)
  50. {
  51. canvas.EndDocument();
  52. throw new LayoutTestException("Exception occured during layout execution", exception);
  53. }
  54. canvas.EndPage();
  55. if (spacePlan.Type == SpacePlanType.FullRender)
  56. break;
  57. }
  58. return (pageSizes, false);
  59. }
  60. ICollection<LayoutTestResult.PageLayout> CollectMockInformation(ICollection<Size> pageSizes)
  61. {
  62. // mock cannot contain another mock, flat structure
  63. var mocks = container.ExtractElementsOfType<ElementMock>().Select(x => x.Value);
  64. return mocks
  65. .SelectMany(x => x.DrawingCommands)
  66. .GroupBy(x => x.PageNumber)
  67. .OrderBy(x => x.Key)
  68. .Select(x => new LayoutTestResult.PageLayout
  69. {
  70. RequiredArea = pageSizes.ElementAt(x.Key - 1),
  71. Mocks = x
  72. .Select(y => new LayoutTestResult.MockLayoutPosition
  73. {
  74. MockId = y.MockId,
  75. Size = y.Size,
  76. Position = y.Position
  77. })
  78. .ToList()
  79. })
  80. .ToList();
  81. }
  82. }
  83. }