test all predefined cmaps and fix bugs

This commit is contained in:
Eliot Jones
2017-12-20 22:52:42 +00:00
parent 078e67893d
commit a0205ab637
3 changed files with 93 additions and 1 deletions

View File

@@ -1,5 +1,9 @@
namespace UglyToad.Pdf.Tests.Fonts.Parser namespace UglyToad.Pdf.Tests.Fonts.Parser
{ {
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using IO;
using Pdf.Fonts.Parser; using Pdf.Fonts.Parser;
using Xunit; using Xunit;
@@ -84,5 +88,42 @@ end";
Assert.Equal("a", cmap.BaseFontCharacterMap[68]); Assert.Equal("a", cmap.BaseFontCharacterMap[68]);
Assert.Equal("x", cmap.BaseFontCharacterMap[91]); Assert.Equal("x", cmap.BaseFontCharacterMap[91]);
} }
[Theory]
[MemberData(nameof(PredefinedCMaps))]
public void CanParseAllPredefinedCMaps(string resourceName)
{
Debug.WriteLine("Parsing: " + resourceName);
var input = new ByteArrayInputBytes(ReadResourceBytes(resourceName));
var cmap = cMapParser.Parse(input, false);
Assert.NotNull(cmap);
}
private static byte[] ReadResourceBytes(string name)
{
using (var resource = typeof(CMapParser).Assembly.GetManifestResourceStream(name))
using (var memoryStream = new MemoryStream())
{
resource.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
public static IEnumerable<object[]> PredefinedCMaps()
{
var resources = typeof(CMapParser).Assembly.GetManifestResourceNames();
foreach (var resource in resources)
{
if (resource.Contains(".CMap."))
{
yield return new object[] {resource};
}
}
}
} }
} }

View File

@@ -97,6 +97,45 @@
throw new InvalidOperationException("The Character Identifier System Information was never set."); throw new InvalidOperationException("The Character Identifier System Information was never set.");
} }
public void UseCMap(CMap other)
{
CodespaceRanges = Combine(CodespaceRanges, other.CodespaceRanges);
CidCharacterMappings = Combine(CidCharacterMappings, other.CidCharacterMappings);
CidRanges = Combine(CidRanges, other.CidRanges);
if (other.BaseFontCharacterMap != null)
{
foreach (var keyValuePair in other.BaseFontCharacterMap)
{
BaseFontCharacterMap[keyValuePair.Key] = keyValuePair.Value;
}
}
}
private static IReadOnlyList<T> Combine<T>(IReadOnlyList<T> a, IReadOnlyList<T> b)
{
if (a == null && b == null)
{
return new T[0];
}
if (a == null)
{
return b;
}
if (b == null)
{
return a;
}
var result = new List<T>(a);
result.AddRange(b);
return result;
}
private int GetCodeFromArray(IReadOnlyList<byte> data, int length) private int GetCodeFromArray(IReadOnlyList<byte> data, int length)
{ {
int code = 0; int code = 0;

View File

@@ -34,7 +34,19 @@
switch (operatorToken.Data) switch (operatorToken.Data)
{ {
case "usecmap": case "usecmap":
throw new NotImplementedException("External CMap files not yet supported, please submit a pull request!"); {
if (previousToken is NameToken name)
{
var external = ParseExternal(name.Data.Name);
builder.UseCMap(external);
}
else
{
throw new InvalidOperationException("Unexpected token preceding external cmap call: " + previousToken);
}
break;
}
case "begincodespacerange": case "begincodespacerange":
{ {
if (previousToken is NumericToken numeric) if (previousToken is NumericToken numeric)