mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-14 19:05:01 +08:00
add some more tests for truetype and tokens
This commit is contained in:
BIN
src/UglyToad.PdfPig.Tests/Fonts/TrueType/Andada-Regular.ttf
Normal file
BIN
src/UglyToad.PdfPig.Tests/Fonts/TrueType/Andada-Regular.ttf
Normal file
Binary file not shown.
@@ -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]
|
||||
|
45
src/UglyToad.PdfPig.Tests/Tokens/BooleanTokenTests.cs
Normal file
45
src/UglyToad.PdfPig.Tests/Tokens/BooleanTokenTests.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
43
src/UglyToad.PdfPig.Tests/Tokens/TestPdfTokenScanner.cs
Normal file
43
src/UglyToad.PdfPig.Tests/Tokens/TestPdfTokenScanner.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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" />
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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; }
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
@@ -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()
|
||||
{
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user