add tests to visually verify the output for glpyh bounding boxes and use advance widths for empty glyphs in truetype fonts

This commit is contained in:
Eliot Jones
2018-04-15 12:47:08 +01:00
parent 9700ee03b8
commit 53f693bc77
11 changed files with 138 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View File

@@ -0,0 +1,87 @@
namespace UglyToad.PdfPig.Tests.Integration.VisualVerification
{
using System;
using System.Drawing;
using System.IO;
using Xunit;
public class GenerateLetterBoundingBoxImages
{
private const string NonLatinAcrobatDistiller = "Single Page Non Latin - from acrobat distiller";
private const string SingleGoogleDrivePage = "Single Page Simple - from google drive";
private const string SinglePageFormattedType0Content = "Type0 Font";
private static string GetFilename(string name)
{
var documentFolder = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "Integration", "Documents"));
if (!name.EndsWith(".pdf"))
{
name += ".pdf";
}
return Path.Combine(documentFolder, name);
}
[Fact]
public void SinglePageNonLatinFromAcrobatDistiller()
{
Run(NonLatinAcrobatDistiller);
}
[Fact]
public void SinglePageSimpleFromGoogleDrive()
{
Run(SingleGoogleDrivePage);
}
[Fact]
public void SinglePageType0Font()
{
Run(SinglePageFormattedType0Content);
}
private static void Run(string file)
{
var pdfFileName = GetFilename(file);
using (var document = PdfDocument.Open(pdfFileName))
using (var image = GetCorrespondingImage(pdfFileName))
{
var page = document.GetPage(1);
var redPen = new Pen(Color.BlueViolet, 1);
using (var bitmap = new Bitmap(image))
using (var graphics = Graphics.FromImage(bitmap))
{
foreach (var word in page.Letters)
{
graphics.DrawRectangle(redPen, new Rectangle((int)word.Rectangle.Left,
792 - (int)word.Rectangle.Top, (int)word.Rectangle.Width, (int)word.Rectangle.Height));
}
var imageName = $"{file}.jpg";
if (!Directory.Exists("Images"))
{
Directory.CreateDirectory("Images");
}
var savePath = Path.Combine("Images", imageName);
bitmap.Save(savePath);
}
}
}
private static Image GetCorrespondingImage(string filename)
{
var pdf = GetFilename(filename);
pdf = pdf.Replace(".pdf", ".jpg");
return Image.FromFile(pdf);
}
}
}

View File

@@ -31,6 +31,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview2-26406-04" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.extensibility.execution" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />

View File

@@ -49,7 +49,7 @@
/// </summary>
public override string ToString()
{
return $"{Rectangle} {Value} {FontName} {PointSize}";
return $"{Value} {Rectangle} {FontName} {PointSize}";
}
}
}

View File

@@ -82,8 +82,6 @@
var fromFont = CidFont.GetWidthFromDictionary(cid);
var box = GetBoundingBox(characterCode);
return fromFont;
}

View File

@@ -90,7 +90,13 @@ namespace UglyToad.PdfPig.Fonts.Simple
public PdfRectangle GetBoundingBox(int characterCode)
{
return GetFontMatrix().Transform(GetBoundingBoxInGlyphSpace(characterCode));
var fontMatrix = GetFontMatrix();
var boundingBox = GetBoundingBoxInGlyphSpace(characterCode);
var result = fontMatrix.Transform(boundingBox);
return result;
}
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
@@ -138,3 +144,4 @@ namespace UglyToad.PdfPig.Fonts.Simple
}
}
}

View File

@@ -24,6 +24,8 @@
public bool IsSimple { get; }
public bool IsEmpty => Points.Length == 0;
public Glyph(bool isSimple, byte[] instructions, int[] endPointsOfContours, GlyphPoint[] points,
PdfRectangle bounds)
{

View File

@@ -14,6 +14,8 @@
GlyphPoint[] Points { get; }
bool IsEmpty { get; }
IGlyphDescription DeepClone();
}

View File

@@ -20,14 +20,9 @@
public TrueTypeFont(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tableHeaders, TableRegister tableRegister)
{
if (tableRegister == null)
{
throw new ArgumentNullException(nameof(tableRegister));
}
Version = version;
TableHeaders = tableHeaders;
TableRegister = tableRegister;
TableRegister = tableRegister ?? throw new ArgumentNullException(nameof(tableRegister));
HeaderTable = tableRegister.HeaderTable;
CMapTable = tableRegister.CMapTable;
GlyphTable = tableRegister.GlyphDataTable;
@@ -38,18 +33,7 @@
{
boundingBox = default(PdfRectangle);
int index;
if (CMapTable == null)
{
if (characterIdentifierToGlyphIndex == null)
{
return false;
}
index = characterIdentifierToGlyphIndex(characterCode);
}
else if (!CMapTable.TryGetGlyphIndex(characterCode, out index))
if (!TryGetGlyphIndex(characterCode, characterIdentifierToGlyphIndex, out var index))
{
return false;
}
@@ -61,8 +45,15 @@
return false;
}
boundingBox = glyph.Bounds;
if (glyph.IsEmpty && TryGetBoundingAdvancedWidthByIndex(index, out var advanceWidth))
{
boundingBox = new PdfRectangle(0, 0, advanceWidth, 0);
}
else
{
boundingBox = glyph.Bounds;
}
return true;
}
@@ -70,18 +61,39 @@
{
width = 0m;
if (!TryGetGlyphIndex(characterCode, null, out var index))
{
return false;
}
return TryGetBoundingAdvancedWidthByIndex(index, out width);
}
private bool TryGetBoundingAdvancedWidthByIndex(int index, out decimal width)
{
width = TableRegister.HorizontalMetricsTable.GetAdvanceWidth(index);
return true;
}
private bool TryGetGlyphIndex(int characterIdentifier, Func<int, int> characterIdentifierToGlyphIndex, out int glyphIndex)
{
glyphIndex = 0;
if (CMapTable == null)
{
return false;
}
if (characterIdentifierToGlyphIndex == null)
{
return false;
}
if (!CMapTable.TryGetGlyphIndex(characterCode, out var index))
glyphIndex = characterIdentifierToGlyphIndex(characterIdentifier);
}
else if (!CMapTable.TryGetGlyphIndex(characterIdentifier, out glyphIndex))
{
return false;
}
width = TableRegister.HorizontalMetricsTable.GetAdvanceWidth(index);
return true;
}
}