-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #408 from steeltomato/enhance-textformatter-and-vi…
…sual-test feat(TextFormatter): Support vertical alignment, overflow, line height
- Loading branch information
Showing
12 changed files
with
339 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -258,4 +258,7 @@ paket-files/ | |
|
||
# Python Tools for Visual Studio (PTVS) | ||
__pycache__/ | ||
*.pyc | ||
*.pyc | ||
|
||
# OSX | ||
.DS_Store |
Binary file added
BIN
+11.7 KB
PdfSharpCore.Test/Assets/Drawing/Layout/DrawMultiLineStringWithOverflow_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+17.4 KB
PdfSharpCore.Test/Assets/Drawing/Layout/DrawMultiLineStringsWithAlignment_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+28.7 KB
PdfSharpCore.Test/Assets/Drawing/Layout/DrawMultiLineStringsWithLineHeight_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+9.65 KB
PdfSharpCore.Test/Assets/Drawing/Layout/DrawMultilineStringWithTruncate_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
using System.IO; | ||
using FluentAssertions; | ||
using ImageMagick; | ||
using PdfSharpCore.Drawing; | ||
using PdfSharpCore.Drawing.Layout; | ||
using PdfSharpCore.Drawing.Layout.enums; | ||
using PdfSharpCore.Pdf; | ||
using PdfSharpCore.Test.Helpers; | ||
using Xunit; | ||
|
||
namespace PdfSharpCore.Test.Drawing.Layout | ||
{ | ||
public class XTextFormatterTest | ||
{ | ||
private static readonly string _outDir = "TestResults/XTextFormatterTest"; | ||
private static readonly string _expectedImagesPath = Path.Combine("Drawing", "Layout"); | ||
|
||
private PdfDocument _document; | ||
private XGraphics _renderer; | ||
private XTextFormatter _textFormatter; | ||
|
||
// Run before each test | ||
public XTextFormatterTest() | ||
{ | ||
_document = new PdfDocument(); | ||
var page = _document.AddPage(); | ||
page.Size = PageSize.A6; // 295 x 417 pts | ||
_renderer = XGraphics.FromPdfPage(page); | ||
_textFormatter = new XTextFormatter(_renderer); | ||
} | ||
|
||
[Fact] | ||
public void DrawSingleLineString() | ||
{ | ||
var layout = new XRect(12, 12, 200, 50); | ||
_textFormatter.DrawString("This is a simple single line test", new XFont("Arial", 12), XBrushes.Black, layout); | ||
|
||
var diffResult = DiffPage(_document, "DrawSingleLineString", 1); | ||
|
||
diffResult.DiffValue.Should().Be(0); | ||
} | ||
|
||
[Fact] | ||
public void DrawMultilineStringWithTruncate() | ||
{ | ||
var layout = new XRect(12, 12, 200, 40); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout); | ||
_textFormatter.DrawString("This is text\nspanning 3 lines\nbut only space for 2", new XFont("Arial", 12), XBrushes.Black, layout); | ||
|
||
var diffResult = DiffPage(_document, "DrawMultilineStringWithTruncate", 1); | ||
|
||
diffResult.DiffValue.Should().Be(0); | ||
} | ||
|
||
[Fact] | ||
public void DrawMultiLineStringWithOverflow() | ||
{ | ||
var layout = new XRect(12, 12, 200, 40); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout); | ||
_textFormatter.AllowVerticalOverflow = true; | ||
_textFormatter.DrawString("This is text\nspanning 3 lines\nand overflow shows all three", new XFont("Arial", 12), XBrushes.Black, layout); | ||
|
||
var diffResult = DiffPage(_document, "DrawMultiLineStringWithOverflow", 1); | ||
|
||
diffResult.DiffValue.Should().Be(0); | ||
} | ||
|
||
[Fact] | ||
public void DrawMultiLineStringsWithAlignment() | ||
{ | ||
var layout1 = new XRect(12, 12, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout1); | ||
_textFormatter.DrawString("This is text\naligned to the top-left", new XFont("Arial", 12), XBrushes.Black, layout1); | ||
|
||
var layout2 = new XRect(12, 100, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout2); | ||
_textFormatter.SetAlignment(new TextFormatAlignment { Horizontal = XParagraphAlignment.Center, Vertical = XVerticalAlignment.Middle}); | ||
_textFormatter.DrawString("This is text\naligned to the middle-center", new XFont("Arial", 12), XBrushes.Black, layout2); | ||
|
||
var layout3 = new XRect(12, 200, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout3); | ||
_textFormatter.SetAlignment(new TextFormatAlignment { Horizontal = XParagraphAlignment.Right, Vertical = XVerticalAlignment.Bottom}); | ||
_textFormatter.DrawString("This is text\naligned to the bottom-right", new XFont("Arial", 12), XBrushes.Black, layout3); | ||
|
||
var diffResult = DiffPage(_document, "DrawMultiLineStringsWithAlignment", 1); | ||
|
||
diffResult.DiffValue.Should().Be(0); | ||
} | ||
|
||
[Fact] | ||
public void DrawMultiLineStringsWithLineHeight() | ||
{ | ||
var font = new XFont("Arial", 12); | ||
|
||
var layout1 = new XRect(10, 10, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout1); | ||
_textFormatter.DrawString("This is text\naligned to the top-left\nand a custom line height", font, XBrushes.Black, layout1, 16); | ||
|
||
var layout2 = new XRect(10, 110, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout2); | ||
_textFormatter.SetAlignment(new TextFormatAlignment { Horizontal = XParagraphAlignment.Center, Vertical = XVerticalAlignment.Middle}); | ||
_textFormatter.DrawString("This is text\naligned to the middle-center\nand a custom line height", font, XBrushes.Black, layout2, 16); | ||
|
||
var layout3 = new XRect(10, 210, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout3); | ||
_textFormatter.SetAlignment(new TextFormatAlignment { Horizontal = XParagraphAlignment.Right, Vertical = XVerticalAlignment.Bottom}); | ||
_textFormatter.DrawString("This is text\naligned to the bottom-right\nand a custom line height", font, XBrushes.Black, layout3, 16); | ||
|
||
var layout4 = new XRect(10, 310, 200, 80); | ||
_renderer.DrawRectangle(XBrushes.LightGray, layout4); | ||
_textFormatter.SetAlignment(new TextFormatAlignment { Horizontal = XParagraphAlignment.Center, Vertical = XVerticalAlignment.Middle}); | ||
_textFormatter.DrawString("This is text\nwith a very small\nline height", font, XBrushes.Black, layout4, 6); | ||
|
||
var diffResult = DiffPage(_document, "DrawMultiLineStringsWithLineHeight", 1); | ||
|
||
diffResult.DiffValue.Should().Be(0); | ||
} | ||
|
||
private static DiffOutput DiffPage(PdfDocument document, string filePrefix, int pageNum) | ||
{ | ||
var rasterized = PdfHelper.Rasterize(document); | ||
var rasterizedFiles = PdfHelper.WriteImageCollection(rasterized.ImageCollection, _outDir, filePrefix); | ||
var expectedImagePath = PathHelper.GetInstance().GetAssetPath(_expectedImagesPath, $"{filePrefix}_{pageNum}.png"); | ||
return PdfHelper.Diff(rasterizedFiles[pageNum-1], expectedImagePath, _outDir, filePrefix); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using ImageMagick; | ||
using PdfSharpCore.Pdf; | ||
|
||
namespace PdfSharpCore.Test.Helpers | ||
{ | ||
public class PdfHelper | ||
{ | ||
private static readonly string _rootPath = PathHelper.GetInstance().RootDir; | ||
|
||
/// <summary> | ||
/// Rasterize all pages within a PDF to PNG images | ||
/// </summary> | ||
/// <returns></returns> | ||
/// <exception cref="Exception"></exception> | ||
public static RasterizeOutput Rasterize(PdfDocument document) | ||
{ | ||
var readerSettings = new MagickReadSettings | ||
{ | ||
Density = new Density(300, 300), | ||
BackgroundColor = MagickColors.White | ||
}; | ||
var images = new MagickImageCollection(); | ||
|
||
// Add all pages to the collection | ||
using var ms = new MemoryStream(); | ||
document.Save(ms); | ||
|
||
try | ||
{ | ||
images.Read(ms, readerSettings); | ||
} | ||
catch (MagickDelegateErrorException ex) | ||
{ | ||
throw new Exception("Ghostscript is not installed or is an incompatible version, unable to rasterize PDF", ex); | ||
} | ||
|
||
// Remove transparency to guarantee a standard white background | ||
foreach (var img in images) | ||
{ | ||
img.Alpha(AlphaOption.Deactivate); | ||
img.BackgroundColor = MagickColors.White; | ||
} | ||
|
||
return new RasterizeOutput | ||
{ | ||
ImageCollection = images, | ||
}; | ||
} | ||
|
||
public static List<string> WriteImageCollection(MagickImageCollection images, string outDir, string filePrefix) | ||
{ | ||
var outPaths = new List<string>(); | ||
for (var pageNum = 0; pageNum < images.Count; pageNum++) | ||
{ | ||
var outPath = GetOutFilePath(outDir, $"{filePrefix}_{pageNum+1}.png"); | ||
images[pageNum].Write(outPath); | ||
outPaths.Add(outPath); | ||
} | ||
|
||
return outPaths; | ||
} | ||
|
||
public static string WriteImage(IMagickImage image, string outDir, string fileNameWithoutExtension) | ||
{ | ||
var outPath = GetOutFilePath(outDir, $"{fileNameWithoutExtension}.png"); | ||
image.Write(outPath); | ||
return outPath; | ||
} | ||
|
||
// Note: For diff to function properly, it requires the underlying image to be in the proper format | ||
// For instance, actual and expected must both be sourced from .png files | ||
public static DiffOutput Diff(string actualImagePath, string expectedImagePath, string outputPath = null, string filePrefix = null, int fuzzPct = 4) | ||
{ | ||
var diffImg = new MagickImage(); | ||
var actual = new MagickImage(actualImagePath); | ||
var expected = new MagickImage(expectedImagePath); | ||
|
||
// Allow for subtle differences due to cross-platform rendering of the PDF fonts | ||
actual.ColorFuzz = new Percentage(fuzzPct); | ||
var diffVal = actual.Compare(expected, ErrorMetric.Absolute, diffImg); | ||
|
||
if (diffVal > 0 && outputPath != null && filePrefix != null) | ||
{ | ||
WriteImage(diffImg, outputPath, $"{filePrefix}_diff"); | ||
} | ||
|
||
return new DiffOutput | ||
{ | ||
DiffValue = diffVal, | ||
DiffImage = diffImg | ||
}; | ||
} | ||
|
||
private static string GetOutFilePath(string outDir, string name) | ||
{ | ||
var dir = Path.Combine(_rootPath, outDir); | ||
Directory.CreateDirectory(dir); | ||
return Path.Combine(dir, name); | ||
} | ||
} | ||
|
||
public class RasterizeOutput | ||
{ | ||
public List<string> OutputPaths; | ||
public MagickImageCollection ImageCollection; | ||
} | ||
|
||
public class DiffOutput | ||
{ | ||
public IMagickImage DiffImage; | ||
public double DiffValue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.