LayoutTestExecutor.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using QuestPDF.Drawing;
  2. using QuestPDF.Drawing.DocumentCanvases;
  3. using QuestPDF.Drawing.Proxy;
  4. using QuestPDF.Elements;
  5. using QuestPDF.Helpers;
  6. using QuestPDF.Infrastructure;
  7. namespace QuestPDF.LayoutTests.TestEngine;
  8. internal static class LayoutTestExecutor
  9. {
  10. public static LayoutTestResult.DocumentLayout Execute(Size pageSize, Container container)
  11. {
  12. var (pageSizes, generatesInfiniteLayout) = GenerateDocument();
  13. container.ReleaseDisposableChildren();
  14. return new LayoutTestResult.DocumentLayout
  15. {
  16. Pages = CollectMockInformation(pageSizes),
  17. GeneratesInfiniteLayout = generatesInfiniteLayout
  18. };
  19. (List<Size> pageSizes, bool generatesInfiniteLayout) GenerateDocument()
  20. {
  21. // inject dependencies
  22. var pageContext = new PageContext();
  23. pageContext.ProceedToNextRenderingPhase();
  24. using var canvas = new CompanionDocumentCanvas();
  25. container.InjectDependencies(pageContext, canvas.GetDrawingCanvas());
  26. // distribute global state
  27. container.ApplyInheritedAndGlobalTexStyle(TextStyle.Default);
  28. container.ApplyContentDirection(ContentDirection.LeftToRight);
  29. container.ApplyDefaultImageConfiguration(DocumentSettings.Default.ImageRasterDpi, DocumentSettings.Default.ImageCompressionQuality, true);
  30. // render
  31. container.VisitChildren(x => (x as IStateful)?.ResetState());
  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. }