add some more tests for truetype and tokens

This commit is contained in:
Eliot Jones
2018-11-25 13:06:54 +00:00
parent 243f3dc099
commit 9f783ddef0
13 changed files with 180 additions and 40 deletions

View File

@@ -2,7 +2,6 @@
{
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using PdfPig.Fonts.TrueType;
using PdfPig.Fonts.TrueType.Parser;
@@ -14,17 +13,13 @@
{
private static byte[] GetFileBytes(string name)
{
var manifestFiles = typeof(TrueTypeFontParserTests).Assembly.GetManifestResourceNames();
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Fonts", "TrueType");
var match = manifestFiles.Single(x => x.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) >= 0);
name = name.EndsWith(".ttf") ? name : name + ".ttf";
using (var memoryStream = new MemoryStream())
using (var stream = typeof(TrueTypeFontParserTests).Assembly.GetManifestResourceStream(match))
{
stream.CopyTo(memoryStream);
var file = Path.Combine(path, name);
return memoryStream.ToArray();
}
return File.ReadAllBytes(file);
}
private readonly TrueTypeFontParser parser = new TrueTypeFontParser();
@@ -136,13 +131,27 @@
}
[Fact]
public void ParseEmbeddedSimpleGoogleDocssGautmi()
public void ParseSimpleGoogleDocssGautmi()
{
var bytes = GetFileBytes("google-simple-doc");
var input = new TrueTypeDataBytes(new ByteArrayInputBytes(bytes));
parser.Parse(input);
var font = parser.Parse(input);
Assert.NotNull(font.GlyphTable);
}
[Fact]
public void ParseAndadaRegular()
{
var bytes = GetFileBytes("Andada-Regular");
var input = new TrueTypeDataBytes(new ByteArrayInputBytes(bytes));
var font = parser.Parse(input);
Assert.NotNull(font.GlyphTable);
}
[Fact]

View File

@@ -0,0 +1,45 @@
namespace UglyToad.PdfPig.Tests.Tokens
{
using PdfPig.Tokens;
using Xunit;
public class BooleanTokenTests
{
[Fact]
public void BooleanTokensObjectEquals()
{
var one = BooleanToken.True;
var two = (object) BooleanToken.True;
Assert.True(one.Equals(two));
}
[Fact]
public void BooleanTokensObjectNotEqual()
{
var one = BooleanToken.False;
var two = (object)BooleanToken.True;
Assert.False(one.Equals(two));
}
[Fact]
public void BooleanTokensHashCodeMatch()
{
Assert.Equal(BooleanToken.True.GetHashCode(), BooleanToken.True.GetHashCode());
}
[Fact]
public void BooleanTokensHashCodeNotMatch()
{
Assert.NotEqual(BooleanToken.True.GetHashCode(), BooleanToken.False.GetHashCode());
}
[Fact]
public void BooleanTokensStringRepresentationCorrect()
{
Assert.Equal("True", BooleanToken.True.ToString());
Assert.Equal("False", BooleanToken.False.ToString());
}
}
}

View File

@@ -3,6 +3,7 @@ namespace UglyToad.PdfPig.Tests.Tokens
{
using System;
using System.Collections.Generic;
using Exceptions;
using PdfPig.Tokens;
using Xunit;
@@ -73,5 +74,43 @@ namespace UglyToad.PdfPig.Tests.Tokens
Assert.True(result);
Assert.Equal("None", Assert.IsType<StringToken>(token).Data);
}
[Fact]
public void CreateWithNonNameTokensThrows()
{
Action action = () => new DictionaryToken(new Dictionary<IToken, IToken>
{
{ new NumericToken(7), NameToken.N }
});
Assert.Throws<PdfDocumentFormatException>(action);
}
[Fact]
public void GetWithObjectNotOfTypeOrReferenceThrows()
{
var dictionary = new DictionaryToken(new Dictionary<IToken, IToken>
{
{ NameToken.Count, new StringToken("twelve") }
});
Action action = () => dictionary.Get<NumericToken>(NameToken.Count, new TestPdfTokenScanner());
Assert.Throws<PdfDocumentFormatException>(action);
}
[Fact]
public void WithCorrectlyAddsKey()
{
var dictionary = new DictionaryToken(new Dictionary<IToken, IToken>
{
{ NameToken.Count, new StringToken("12") }
});
var newDictionary = dictionary.With(NameToken.ActualText, new StringToken("The text"));
Assert.True(newDictionary.ContainsKey(NameToken.ActualText));
Assert.Equal("The text", newDictionary.Get<StringToken>(NameToken.ActualText, new TestPdfTokenScanner()).Data);
}
}
}

View File

@@ -0,0 +1,43 @@
// ReSharper disable ObjectCreationAsStatement
namespace UglyToad.PdfPig.Tests.Tokens
{
using System;
using PdfPig.Tokenization;
using PdfPig.Tokenization.Scanner;
using PdfPig.Tokens;
internal class TestPdfTokenScanner : IPdfTokenScanner
{
public bool MoveNext()
{
throw new NotImplementedException();
}
public IToken CurrentToken { get; set; }
public bool TryReadToken<T>(out T token) where T : class, IToken
{
throw new NotImplementedException();
}
public void Seek(long position)
{
throw new NotImplementedException();
}
public long CurrentPosition { get; set; }
public void RegisterCustomTokenizer(byte firstByte, ITokenizer tokenizer)
{
throw new NotImplementedException();
}
public void DeregisterCustomTokenizer(ITokenizer tokenizer)
{
throw new NotImplementedException();
}
public ObjectToken Get(IndirectReference reference)
{
throw new NotImplementedException();
}
}
}

View File

@@ -30,6 +30,9 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="Fonts\TrueType\Andada-Regular.ttf" />
<EmbeddedResource Remove="Fonts\TrueType\google-simple-doc.ttf" />
<EmbeddedResource Remove="Fonts\TrueType\Roboto-Regular.ttf" />
<EmbeddedResource Remove="Fonts\Type1\AdobeUtopia.pfa" />
<EmbeddedResource Remove="Fonts\Type1\CMBX10.pfa" />
<EmbeddedResource Remove="Fonts\Type1\CMBX12.pfa" />
@@ -45,6 +48,15 @@
<Content Include="Fonts\CompactFontFormat\MinionPro.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Fonts\TrueType\Andada-Regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Fonts\TrueType\google-simple-doc.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Fonts\TrueType\Roboto-Regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Fonts\Type1\AdobeUtopia.pfa" />
<Content Include="Fonts\Type1\CMBX10.pfa" />
<Content Include="Fonts\Type1\CMBX12.pfa" />

View File

@@ -71,7 +71,7 @@
return new TrueTypeSimpleFont(name, descriptor, toUnicodeCMap, encoding, font, firstCharacter, widths);
}
private TrueTypeFont ParseTrueTypeFont(FontDescriptor descriptor)
private TrueTypeFontProgram ParseTrueTypeFont(FontDescriptor descriptor)
{
if (descriptor?.FontFile == null)
{

View File

@@ -22,7 +22,7 @@
private readonly Encoding encoding;
[CanBeNull]
private readonly TrueTypeFont font;
private readonly TrueTypeFontProgram fontProgram;
private readonly int firstCharacter;
@@ -39,13 +39,13 @@
FontDescriptor descriptor,
[CanBeNull] CMap toUnicodeCMap,
[CanBeNull] Encoding encoding,
[CanBeNull] TrueTypeFont font,
[CanBeNull] TrueTypeFontProgram fontProgram,
int firstCharacter,
decimal[] widths)
{
this.descriptor = descriptor;
this.encoding = encoding;
this.font = font;
this.fontProgram = fontProgram;
this.firstCharacter = firstCharacter;
this.widths = widths;
@@ -115,9 +115,9 @@
fromFont = false;
width = widths[index];
}
else if (font != null)
else if (fontProgram != null)
{
if (!font.TryGetBoundingAdvancedWidth(characterCode, out width))
if (!fontProgram.TryGetBoundingAdvancedWidth(characterCode, out width))
{
width = boundingBoxPreTransform;
}
@@ -143,17 +143,17 @@
{
fromFont = true;
if (font == null)
if (fontProgram == null)
{
return descriptor.BoundingBox;
}
if (font.TryGetBoundingBox(characterCode, out var bounds))
if (fontProgram.TryGetBoundingBox(characterCode, out var bounds))
{
return bounds;
}
if (font.TryGetBoundingAdvancedWidth(characterCode, out var width))
if (fontProgram.TryGetBoundingAdvancedWidth(characterCode, out var width))
{
return new PdfRectangle(0, 0, width, 0);
}
@@ -179,9 +179,9 @@
{
var scale = 1000m;
if (font?.HeaderTable != null)
if (fontProgram?.HeaderTable != null)
{
scale = font.GetFontMatrixMultiplier();
scale = fontProgram.GetFontMatrixMultiplier();
}
return TransformationMatrix.FromValues(1m / scale, 0, 0, 1m / scale, 0, 0);

View File

@@ -23,7 +23,7 @@
/// <summary>
/// Defines mapping of character codes to glyph index values in the font.
/// Can contain mutliple sub-tables to support multiple encoding schemes.
/// Can contain multiple sub-tables to support multiple encoding schemes.
/// Where a character code isn't found it should map to index 0.
/// </summary>
public CMapTable CMapTable { get; set; }

View File

@@ -7,7 +7,7 @@
internal class TrueTypeFontParser
{
public TrueTypeFont Parse(TrueTypeDataBytes data)
public TrueTypeFontProgram Parse(TrueTypeDataBytes data)
{
var version = (decimal)data.Read32Fixed();
int numberOfTables = data.ReadUnsignedShort();
@@ -53,7 +53,7 @@
return new TrueTypeHeaderTable(tag, checksum, offset, length);
}
private static TrueTypeFont ParseTables(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tables, TrueTypeDataBytes data)
private static TrueTypeFontProgram ParseTables(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tables, TrueTypeDataBytes data)
{
var isPostScript = tables.ContainsKey(TrueTypeHeaderTable.Cff);
@@ -111,7 +111,7 @@
OptionallyParseTables(tables, data, tableRegister);
}
return new TrueTypeFont(version, tables, tableRegister);
return new TrueTypeFontProgram(version, tables, tableRegister);
}
private static void OptionallyParseTables(IReadOnlyDictionary<string, TrueTypeHeaderTable> tables, TrueTypeDataBytes data, TableRegister tableRegister)

View File

@@ -7,7 +7,7 @@
using Parser;
using Tables;
internal class TrueTypeFont : ICidFontProgram
internal class TrueTypeFontProgram : ICidFontProgram
{
public decimal Version { get; }
@@ -18,7 +18,7 @@
public GlyphDataTable GlyphTable { get; }
public TableRegister TableRegister { get; }
public TrueTypeFont(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tableHeaders, TableRegister tableRegister)
public TrueTypeFontProgram(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tableHeaders, TableRegister tableRegister)
{
Version = version;
TableHeaders = tableHeaders;

View File

@@ -5,7 +5,7 @@
/// <summary>
/// The boolean object either <see cref="True"/> (<see langword="true"/>) or <see cref="False"/> (<see langword="true"/>).
/// </summary>
public class BooleanToken : IDataToken<bool>
public sealed class BooleanToken : IDataToken<bool>
{
/// <summary>
/// The boolean token corresponding to <see langword="true"/>.
@@ -43,15 +43,7 @@
return other.Data == Data;
}
/// <summary>
/// Check if two boolean tokens are equal in value.
/// </summary>
protected bool Equals(BooleanToken other)
{
return Data == other.Data;
}
/// <inheritdoc />
public override int GetHashCode()
{

View File

@@ -42,7 +42,7 @@
else
{
// For now:
throw new PdfDocumentFormatException("Key for dictionary token was not a string! " + keyValuePair.Key);
throw new PdfDocumentFormatException($"Key for dictionary token was not a name! {keyValuePair.Key}");
}
}
@@ -60,7 +60,7 @@
{
if (!(token is IndirectReferenceToken indirectReference))
{
throw new InvalidOperationException($"Dictionary does not contain token with name {name} of type {typeof(T).Name}.");
throw new PdfDocumentFormatException($"Dictionary does not contain token with name {name} of type {typeof(T).Name}.");
}
typedToken = DirectObjectFinder.Get<T>(indirectReference, scanner);