PdfPig/src/UglyToad.PdfPig.Tests/Writer/PdfDocumentBuilderTests.cs
Eliot Jones 90f8f97bfd add simple test case for subsetting issue #98
adds a single test which proves that the invalid truetype subsetting with roboto is related to our font subsetting code, since we can subset the same text correctly with windows calibri we must be reading roboto incorrectly.
2020-01-04 10:27:07 +00:00

393 lines
13 KiB
C#

namespace UglyToad.PdfPig.Tests.Writer
{
using System.IO;
using System.Linq;
using Content;
using PdfPig.Fonts;
using PdfPig.Geometry;
using PdfPig.Util;
using PdfPig.Writer;
using Tests.Fonts.TrueType;
using Xunit;
public class PdfDocumentBuilderTests
{
[Fact]
public void CanWriteSingleBlankPage()
{
var result = CreateSingleBlankPage();
WriteFile(nameof(CanWriteSinglePageHelloWorld), result);
Assert.NotEmpty(result);
var str = OtherEncodings.BytesAsLatin1String(result);
Assert.StartsWith("%PDF", str);
Assert.EndsWith("%%EOF", str);
}
[Fact]
public void CanReadSingleBlankPage()
{
var result = CreateSingleBlankPage();
using (var document = PdfDocument.Open(result, new ParsingOptions { UseLenientParsing = false }))
{
Assert.Equal(1, document.NumberOfPages);
var page = document.GetPage(1);
Assert.Equal(PageSize.A4, page.Size);
Assert.Empty(page.Letters);
Assert.NotNull(document.Structure.Catalog);
foreach (var offset in document.Structure.CrossReferenceTable.ObjectOffsets)
{
var obj = document.Structure.GetObject(offset.Key);
Assert.NotNull(obj);
}
}
}
private static byte[] CreateSingleBlankPage()
{
var builder = new PdfDocumentBuilder();
builder.AddPage(PageSize.A4);
var result = builder.Build();
return result;
}
[Fact]
public void CanWriteSinglePageStandard14FontHelloWorld()
{
var builder = new PdfDocumentBuilder();
PdfPageBuilder page = builder.AddPage(PageSize.A4);
PdfDocumentBuilder.AddedFont font = builder.AddStandard14Font(Standard14Font.Helvetica);
page.AddText("Hello World!", 12, new PdfPoint(25, 520), font);
var b = builder.Build();
WriteFile(nameof(CanWriteSinglePageStandard14FontHelloWorld), b);
using (var document = PdfDocument.Open(b))
{
var page1 = document.GetPage(1);
Assert.Equal(new[] {"Hello", "World!"}, page1.GetWords().Select(x => x.Text));
}
}
[Fact]
public void CanWriteSinglePageHelloWorld()
{
var builder = new PdfDocumentBuilder();
var page = builder.AddPage(PageSize.A4);
page.DrawLine(new PdfPoint(30, 520), new PdfPoint(360, 520));
page.DrawLine(new PdfPoint(360, 520), new PdfPoint(360, 250));
page.SetStrokeColor(250, 132, 131);
page.DrawLine(new PdfPoint(25, 70), new PdfPoint(100, 70), 3);
page.ResetColor();
page.DrawRectangle(new PdfPoint(30, 200), 250, 100, 0.5m);
page.DrawRectangle(new PdfPoint(30, 100), 250, 100, 0.5m);
var file = TrueTypeTestHelper.GetFileBytes("Andada-Regular.ttf");
var font = builder.AddTrueTypeFont(file);
var letters = page.AddText("Hello World!", 12, new PdfPoint(30, 50), font);
Assert.NotEmpty(page.Operations);
var b = builder.Build();
WriteFile(nameof(CanWriteSinglePageHelloWorld), b);
Assert.NotEmpty(b);
using (var document = PdfDocument.Open(b))
{
var page1 = document.GetPage(1);
Assert.Equal("Hello World!", page1.Text);
var h = page1.Letters[0];
Assert.Equal("H", h.Value);
Assert.Equal("Andada-Regular", h.FontName);
var comparer = new DoubleComparer(0.01);
var pointComparer = new PointComparer(comparer);
for (int i = 0; i < page1.Letters.Count; i++)
{
var readerLetter = page1.Letters[i];
var writerLetter = letters[i];
Assert.Equal(readerLetter.Value, writerLetter.Value);
Assert.Equal(readerLetter.Location, writerLetter.Location, pointComparer);
Assert.Equal(readerLetter.FontSize, writerLetter.FontSize, comparer);
Assert.Equal(readerLetter.GlyphRectangle.Width, writerLetter.GlyphRectangle.Width, comparer);
Assert.Equal(readerLetter.GlyphRectangle.Height, writerLetter.GlyphRectangle.Height, comparer);
Assert.Equal(readerLetter.GlyphRectangle.BottomLeft, writerLetter.GlyphRectangle.BottomLeft, pointComparer);
}
}
}
[Fact]
public void CanWriteRobotoAccentedCharacters()
{
var builder = new PdfDocumentBuilder();
builder.DocumentInformation.Title = "Hello Roboto!";
var page = builder.AddPage(PageSize.A4);
var font = builder.AddTrueTypeFont(TrueTypeTestHelper.GetFileBytes("Roboto-Regular.ttf"));
page.AddText("eé", 12, new PdfPoint(30, 520), font);
Assert.NotEmpty(page.Operations);
var b = builder.Build();
WriteFile(nameof(CanWriteRobotoAccentedCharacters), b);
Assert.NotEmpty(b);
using (var document = PdfDocument.Open(b))
{
var page1 = document.GetPage(1);
Assert.Equal("eé", page1.Text);
}
}
[Fact]
public void WindowsOnlyCanWriteSinglePageAccentedCharactersSystemFont()
{
var builder = new PdfDocumentBuilder();
builder.DocumentInformation.Title = "Hello Windows!";
var page = builder.AddPage(PageSize.A4);
var file = @"C:\Windows\Fonts\Calibri.ttf";
if (!File.Exists(file))
{
return;
}
byte[] bytes;
try
{
bytes = File.ReadAllBytes(file);
}
catch
{
return;
}
var font = builder.AddTrueTypeFont(bytes);
page.AddText("eé", 12, new PdfPoint(30, 520), font);
Assert.NotEmpty(page.Operations);
var b = builder.Build();
WriteFile(nameof(WindowsOnlyCanWriteSinglePageAccentedCharactersSystemFont), b);
Assert.NotEmpty(b);
using (var document = PdfDocument.Open(b))
{
var page1 = document.GetPage(1);
Assert.Equal("eé", page1.Text);
}
}
[Fact]
public void WindowsOnlyCanWriteSinglePageHelloWorldSystemFont()
{
var builder = new PdfDocumentBuilder();
builder.DocumentInformation.Title = "Hello Windows!";
var page = builder.AddPage(PageSize.A4);
var file = @"C:\Windows\Fonts\BASKVILL.TTF";
if (!File.Exists(file))
{
return;
}
byte[] bytes;
try
{
bytes = File.ReadAllBytes(file);
}
catch
{
return;
}
var font = builder.AddTrueTypeFont(bytes);
var letters = page.AddText("Hello World!", 16, new PdfPoint(30, 520), font);
page.AddText("This is some further text continuing to write", 12, new PdfPoint(30, 500), font);
Assert.NotEmpty(page.Operations);
var b = builder.Build();
WriteFile(nameof(WindowsOnlyCanWriteSinglePageHelloWorldSystemFont), b);
Assert.NotEmpty(b);
using (var document = PdfDocument.Open(b))
{
var page1 = document.GetPage(1);
Assert.StartsWith("Hello World!", page1.Text);
var h = page1.Letters[0];
Assert.Equal("H", h.Value);
Assert.Equal("BaskOldFace", h.FontName);
var comparer = new DoubleComparer(0.01);
var pointComparer = new PointComparer(comparer);
for (int i = 0; i < letters.Count; i++)
{
var readerLetter = page1.Letters[i];
var writerLetter = letters[i];
Assert.Equal(readerLetter.Value, writerLetter.Value);
Assert.Equal(readerLetter.Location, writerLetter.Location, pointComparer);
Assert.Equal(readerLetter.FontSize, writerLetter.FontSize, comparer);
Assert.Equal(readerLetter.GlyphRectangle.Width, writerLetter.GlyphRectangle.Width, comparer);
Assert.Equal(readerLetter.GlyphRectangle.Height, writerLetter.GlyphRectangle.Height, comparer);
Assert.Equal(readerLetter.GlyphRectangle.BottomLeft, writerLetter.GlyphRectangle.BottomLeft, pointComparer);
}
}
}
[Fact]
public void CanWriteSinglePageWithAccentedCharacters()
{
var builder = new PdfDocumentBuilder();
var page = builder.AddPage(PageSize.A4);
var file = TrueTypeTestHelper.GetFileBytes("Roboto-Regular.ttf");
var font = builder.AddTrueTypeFont(file);
page.AddText("é (lower case, upper case É).", 9,
new PdfPoint(30, page.PageSize.Height - 50), font);
var bytes = builder.Build();
WriteFile(nameof(CanWriteSinglePageWithAccentedCharacters), bytes);
using (var document = PdfDocument.Open(bytes))
{
var page1 = document.GetPage(1);
Assert.Equal("é (lower case, upper case É).", page1.Text);
}
}
[Fact]
public void CanWriteTwoPageDocument()
{
var builder = new PdfDocumentBuilder();
var page1 = builder.AddPage(PageSize.A4);
var page2 = builder.AddPage(PageSize.A4);
var font = builder.AddTrueTypeFont(TrueTypeTestHelper.GetFileBytes("Roboto-Regular.ttf"));
var topLine = new PdfPoint(30, page1.PageSize.Height - 60);
var letters = page1.AddText("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", 9, topLine, font);
page1.AddText("incididunt ut labore et dolore magna aliqua.", 9, new PdfPoint(30, topLine.Y - letters.Max(x => x.GlyphRectangle.Height) - 5), font);
var page2Letters = page2.AddText("The very hungry caterpillar ate all the apples in the garden.", 12, topLine, font);
var left = (decimal)page2Letters[0].GlyphRectangle.Left;
var bottom = (decimal)page2Letters.Min(x => x.GlyphRectangle.Bottom);
var right = (decimal)page2Letters[page2Letters.Count - 1].GlyphRectangle.Right;
var top = (decimal)page2Letters.Max(x => x.GlyphRectangle.Top);
page2.SetStrokeColor(10, 250, 69);
page2.DrawRectangle(new PdfPoint(left, bottom), right - left, top - bottom);
var bytes = builder.Build();
WriteFile(nameof(CanWriteTwoPageDocument), bytes);
using (var document = PdfDocument.Open(bytes))
{
var page1Out = document.GetPage(1);
Assert.StartsWith("Lorem ipsum dolor sit", page1Out.Text);
var page2Out = document.GetPage(2);
Assert.StartsWith("The very hungry caterpillar", page2Out.Text);
}
}
[Fact]
public void CanWriteSinglePageWithCzechCharacters()
{
var builder = new PdfDocumentBuilder();
var page = builder.AddPage(PageSize.A4);
var font = builder.AddTrueTypeFont(TrueTypeTestHelper.GetFileBytes("Roboto-Regular.ttf"));
page.AddText("Hello: řó", 9,
new PdfPoint(30, page.PageSize.Height - 50), font);
var bytes = builder.Build();
WriteFile(nameof(CanWriteSinglePageWithCzechCharacters), bytes);
using (var document = PdfDocument.Open(bytes))
{
var page1 = document.GetPage(1);
Assert.Equal("Hello: řó", page1.Text);
}
}
private static void WriteFile(string name, byte[] bytes)
{
try
{
if (!Directory.Exists("Builder"))
{
Directory.CreateDirectory("Builder");
}
var output = Path.Combine("Builder", $"{name}.pdf");
File.WriteAllBytes(output, bytes);
}
catch
{
// ignored.
}
}
}
}