Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

176 строки
7.0KB

  1. using System.Drawing;
  2. using DebenuPDFLibraryDLL1013;
  3. using EnvelopeRenderer.Cli.Render;
  4. #pragma warning disable CA1416
  5. namespace EnvelopeRenderer.Cli.Tests;
  6. /// <summary>A &lt;text&gt; element with <c>fill</c> is a filled rectangle (cover-up) that its own text,
  7. /// or any element with a higher render order, draws over.</summary>
  8. public class FilledRectangleTests
  9. {
  10. private static string WriteTemplate(string xml)
  11. {
  12. var path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xml");
  13. File.WriteAllText(path, xml);
  14. return path;
  15. }
  16. private static string DllPath() => Path.Combine(
  17. AppContext.BaseDirectory,
  18. Environment.Is64BitProcess ? "DebenuPDFLibrary64DLL1013.dll" : "DebenuPDFLibraryDLL1013.dll");
  19. [Fact]
  20. public void Parse_FillWithBoxAndNoText_IsAPureRectangle()
  21. {
  22. var path = WriteTemplate("""
  23. <envelopeTemplate pageWidth="297" pageHeight="684">
  24. <text x="10" y="20" font="Arial" size="12" width="100" height="40" fill="#FFFFFF" />
  25. </envelopeTemplate>
  26. """);
  27. var result = TemplateXmlParser.Parse(path);
  28. Assert.True(result.Succeeded, string.Join("; ", result.Errors));
  29. var element = Assert.Single(result.Document!.Elements);
  30. Assert.True(element.HasFill);
  31. Assert.Equal(new PdfColor(255, 255, 255), element.FillColor);
  32. Assert.Equal(string.Empty, element.Runs[0].Literal);
  33. }
  34. [Theory]
  35. [InlineData("""<text x="1" y="2" font="Arial" size="12" fill="#FFFFFF">Hi</text>""", "'width' and 'height'")]
  36. [InlineData("""<text x="1" y="2" font="Arial" size="12" width="5" height="5" fill="nope">Hi</text>""", "'fill'")]
  37. [InlineData("""<text x="1" y="2" font="Arial" size="12" width="5" height="5" fill="#000000" angle="10">Hi</text>""", "rotated")]
  38. public void Parse_InvalidFill_Fails(string textXml, string expected)
  39. {
  40. var result = TemplateXmlParser.Parse(WriteTemplate(
  41. $"""<envelopeTemplate pageWidth="297" pageHeight="684">{textXml}</envelopeTemplate>"""));
  42. Assert.False(result.Succeeded);
  43. Assert.Contains(result.Errors, e => e.Contains(expected));
  44. }
  45. [Fact]
  46. public void Render_FillElement_ProducesDrawWithFillColorAndBox_InRenderOrder()
  47. {
  48. var elements = new[]
  49. {
  50. new TemplateElement(10, 20, "Arial", 12, new[] { new TemplateTextRun(string.Empty, null) },
  51. Width: 100, Height: 40, FillColor: new PdfColor(255, 255, 255)),
  52. TemplateElement.Static(12, 30, "Arial", 12, "over") with { RenderOrder = 1 },
  53. };
  54. var template = new TemplateDocument(297, 684, elements, Array.Empty<TemplateAddressControl>());
  55. var draws = new List<IReadOnlyList<TextDraw>>();
  56. var renderer = new CapturingRenderer(draws);
  57. var result = RenderEngine.Render(
  58. template, new[] { "A" },
  59. new List<IReadOnlyDictionary<string, string>> { new Dictionary<string, string> { ["A"] = "1" } },
  60. renderer, "out.pdf");
  61. Assert.True(result.Succeeded, string.Join("; ", result.Errors));
  62. Assert.Equal(new PdfColor(255, 255, 255), draws[0][0].FillColor);
  63. Assert.Equal(100, draws[0][0].Width);
  64. Assert.Equal("over", draws[0][1].Text);
  65. Assert.Null(draws[0][1].FillColor);
  66. }
  67. private sealed class CapturingRenderer : IPdfRenderer
  68. {
  69. private readonly List<IReadOnlyList<TextDraw>> _draws;
  70. public CapturingRenderer(List<IReadOnlyList<TextDraw>> draws) => _draws = draws;
  71. public bool AddPage(double w, double h, IReadOnlyList<TextDraw> draws, PageBackground? background, out string? error)
  72. {
  73. _draws.Add(draws);
  74. error = null;
  75. return true;
  76. }
  77. public bool Save(string outputPath, out string? error)
  78. {
  79. error = null;
  80. return true;
  81. }
  82. public void Dispose() { }
  83. }
  84. [Fact]
  85. public void RealRender_FilledRectangleCoversBackground_AndTextDrawsOverIt()
  86. {
  87. var key = DebenuLicenseKey.Resolve();
  88. if (key is null)
  89. {
  90. Console.WriteLine("SKIPPED: no Debenu license key available locally.");
  91. return;
  92. }
  93. var dir = Path.Combine(Path.GetTempPath(), $"rect-{Guid.NewGuid():N}");
  94. Directory.CreateDirectory(dir);
  95. try
  96. {
  97. var imagePath = Path.Combine(dir, "red.png");
  98. using (var bitmap = new Bitmap(40, 40))
  99. {
  100. using var g = Graphics.FromImage(bitmap);
  101. g.Clear(Color.Red);
  102. bitmap.Save(imagePath, System.Drawing.Imaging.ImageFormat.Png);
  103. }
  104. // 200x200 page, red background; a white 100x100 rectangle at (50,50) with black text in it.
  105. var rectangle = new TemplateElement(50, 50, "Arial", 40,
  106. new[] { new TemplateTextRun("MMMM", null) },
  107. Width: 100, Height: 100, FillColor: new PdfColor(255, 255, 255));
  108. var template = new TemplateDocument(200, 200, new[] { rectangle },
  109. Array.Empty<TemplateAddressControl>(),
  110. new TemplateBackground("red.png", null, 1, null, dir));
  111. var output = Path.Combine(dir, "out.pdf");
  112. Assert.True(DebenuPdfRenderer.TryCreate(DllPath(), key, out var renderer, out var error), error);
  113. using (renderer)
  114. {
  115. var result = RenderEngine.Render(
  116. template, new[] { "A" },
  117. new List<IReadOnlyDictionary<string, string>> { new Dictionary<string, string> { ["A"] = "1" } },
  118. renderer!, output);
  119. Assert.True(result.Succeeded, string.Join("; ", result.Errors));
  120. }
  121. var pdf = new PDFLibrary(DllPath());
  122. pdf.UnlockKey(key);
  123. Assert.NotEqual(0, pdf.LoadFromFile(output, ""));
  124. var png = Path.Combine(dir, "page.png");
  125. Assert.NotEqual(0, pdf.RenderPageToFile(72, 1, 0, png));
  126. pdf.ReleaseLibrary();
  127. using var rendered = new Bitmap(png);
  128. var corner = rendered.GetPixel(5, 5);
  129. Assert.True(corner.R > 200 && corner.G < 60, $"outside the rectangle the red background stays: {corner}");
  130. // Inside the rectangle (PDF y=50..150 is image rows 50..150): white except where text draws.
  131. int white = 0, dark = 0, red = 0;
  132. for (var x = 55; x < 145; x++)
  133. {
  134. for (var y = 55; y < 145; y++)
  135. {
  136. var c = rendered.GetPixel(x, y);
  137. if (c.R > 230 && c.G > 230 && c.B > 230) { white++; }
  138. else if (c.R < 90 && c.G < 90 && c.B < 90) { dark++; }
  139. else if (c.R > 200 && c.G < 60 && c.B < 60) { red++; }
  140. }
  141. }
  142. Assert.Equal(0, red);
  143. Assert.True(white > 3000, $"the rectangle should be mostly white: {white}");
  144. Assert.True(dark > 100, $"text should draw over the rectangle: {dark}");
  145. }
  146. finally
  147. {
  148. Directory.Delete(dir, recursive: true);
  149. }
  150. }
  151. }

Powered by TurnKey Linux.