ElementObserver.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using System.Diagnostics;
  2. using QuestPDF.Drawing.DrawingCanvases;
  3. using QuestPDF.Drawing.Proxy;
  4. using QuestPDF.Elements;
  5. namespace QuestPDF.LayoutTests.TestEngine;
  6. internal class ElementObserver : ContainerElement
  7. {
  8. public string? ObserverId { get; set; }
  9. public DrawingRecorder? DrawingRecorder { get; set; }
  10. internal override void Draw(Size availableSpace)
  11. {
  12. Debug.Assert(ObserverId != null);
  13. Debug.Assert(DrawingRecorder != null);
  14. var matrix = Canvas.GetCurrentMatrix();
  15. var drawingEvent = new ElementDrawingEvent
  16. {
  17. ObserverId = ObserverId,
  18. PageNumber = PageContext.CurrentPage,
  19. Position = new Position(matrix.TranslateX, matrix.TranslateY),
  20. Size = ObserverId == "$document" ? Child.Measure(availableSpace) : availableSpace
  21. };
  22. if (!IsDiscardDrawingCanvas())
  23. DrawingRecorder?.Record(drawingEvent);
  24. var matrixBeforeDraw = Canvas.GetCurrentMatrix().ToMatrix4x4();
  25. base.Draw(availableSpace);
  26. var matrixAfterDraw = Canvas.GetCurrentMatrix().ToMatrix4x4();
  27. if (matrixAfterDraw != matrixBeforeDraw)
  28. throw new InvalidOperationException("Canvas state was not restored after drawing operation.");
  29. drawingEvent.StateAfterDrawing = (GetRealChild() as IStateful)?.GetState();
  30. }
  31. private Element GetRealChild()
  32. {
  33. var result = Child;
  34. while (true)
  35. {
  36. if (result is ElementProxy proxy)
  37. {
  38. result = proxy.Child;
  39. continue;
  40. }
  41. if (result is DebugPointer debugPointer)
  42. {
  43. result = debugPointer.Child;
  44. continue;
  45. }
  46. break;
  47. }
  48. return result;
  49. }
  50. private bool IsDiscardDrawingCanvas()
  51. {
  52. var canvasUnderTest = Canvas;
  53. while (canvasUnderTest is ProxyDrawingCanvas proxy)
  54. canvasUnderTest = proxy.Target;
  55. return canvasUnderTest is DiscardDrawingCanvas;
  56. }
  57. }