LayoutTestExecutor.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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 class LayoutTestExecutor
  8. {
  9. public static ICollection<LayoutTestResult.PageLayoutSnapshot> Execute(Size pageSize, Container container)
  10. {
  11. var pageSizes = new List<Size>();
  12. GenerateDocument();
  13. return CollectMockInformation();
  14. void GenerateDocument()
  15. {
  16. // inject dependencies
  17. var pageContext = new PageContext();
  18. pageContext.ResetPageNumber();
  19. var canvas = new PreviewerCanvas();
  20. container.InjectDependencies(pageContext, canvas);
  21. // distribute global state
  22. container.ApplyInheritedAndGlobalTexStyle(TextStyle.Default);
  23. container.ApplyContentDirection(ContentDirection.LeftToRight);
  24. container.ApplyDefaultImageConfiguration(DocumentSettings.Default.ImageRasterDpi, DocumentSettings.Default.ImageCompressionQuality, true);
  25. // render
  26. container.VisitChildren(x => (x as IStateResettable)?.ResetState());
  27. canvas.BeginDocument();
  28. while(true)
  29. {
  30. var spacePlan = container.Measure(pageSize);
  31. pageSizes.Add(spacePlan);
  32. if (spacePlan.Type == SpacePlanType.Wrap)
  33. {
  34. canvas.EndDocument();
  35. throw new LayoutTestException("Provided layout generates infinite document");
  36. }
  37. try
  38. {
  39. canvas.BeginPage(pageSize);
  40. container.Draw(pageSize);
  41. pageContext.IncrementPageNumber();
  42. }
  43. catch (Exception exception)
  44. {
  45. canvas.EndDocument();
  46. throw new LayoutTestException("Exception occured during layout execution", exception);
  47. }
  48. canvas.EndPage();
  49. if (spacePlan.Type == SpacePlanType.FullRender)
  50. break;
  51. }
  52. }
  53. ICollection<LayoutTestResult.PageLayoutSnapshot> CollectMockInformation()
  54. {
  55. // mock cannot contain another mock, flat structure
  56. var mocks = container.ExtractElementsOfType<ElementMock>().Select(x => x.Value);
  57. return mocks
  58. .SelectMany(x => x.DrawingCommands)
  59. .GroupBy(x => x.PageNumber)
  60. .Select(x => new LayoutTestResult.PageLayoutSnapshot
  61. {
  62. RequiredArea = pageSizes[x.Key - 1],
  63. MockPositions = x
  64. .Select(y => new LayoutTestResult.MockLayoutPosition
  65. {
  66. MockId = y.MockId,
  67. Size = y.Size,
  68. Position = y.Position
  69. })
  70. .ToList()
  71. })
  72. .ToList();
  73. }
  74. }
  75. }