finish moving all parsing to token scanner

This commit is contained in:
Eliot Jones
2018-01-20 00:49:53 +00:00
parent a0deab446b
commit c5e3ce7ec7
37 changed files with 422 additions and 447 deletions

View File

@@ -1,15 +1,18 @@
namespace UglyToad.PdfPig.Tests.Filters namespace UglyToad.PdfPig.Tests.Filters
{ {
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using PdfPig.ContentStream;
using PdfPig.Filters; using PdfPig.Filters;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
public class Ascii85FilterTests public class Ascii85FilterTests
{ {
private readonly Ascii85Filter filter = new Ascii85Filter(); private readonly Ascii85Filter filter = new Ascii85Filter();
private readonly DictionaryToken dictionary = new DictionaryToken(new Dictionary<IToken, IToken>());
[Fact] [Fact]
public void DecodesWikipediaExample() public void DecodesWikipediaExample()
{ {
@@ -20,7 +23,7 @@ O<DJ+*.@<*K0@<6L(Df-\0Ec5e;DffZ(EZee.Bl.9pF""AGXBPCsi + DGm >@3BB / F * &OCAfu2
l(DId<j@<? 3r@:F % a + D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G l(DId<j@<? 3r@:F % a + D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G
> uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c~>"); > uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c~>");
var result = filter.Decode(bytes, new PdfDictionary(), 0); var result = filter.Decode(bytes, dictionary, 0);
var text = Encoding.ASCII.GetString(result); var text = Encoding.ASCII.GetString(result);
@@ -35,7 +38,7 @@ O<DJ+*.@<*K0@<6L(Df-\0Ec5e;DffZ(EZee.Bl.9pF""AGXBPCsi + DGm >@3BB / F * &OCAfu2
{ {
var bytes = Encoding.ASCII.GetBytes("9jqo^zBlbD-"); var bytes = Encoding.ASCII.GetBytes("9jqo^zBlbD-");
var result = filter.Decode(bytes, new PdfDictionary(), 1); var result = filter.Decode(bytes, dictionary, 1);
var text = Encoding.ASCII.GetString(result); var text = Encoding.ASCII.GetString(result);
@@ -47,7 +50,7 @@ O<DJ+*.@<*K0@<6L(Df-\0Ec5e;DffZ(EZee.Bl.9pF""AGXBPCsi + DGm >@3BB / F * &OCAfu2
{ {
var bytes = Encoding.ASCII.GetBytes("qjzqo^"); var bytes = Encoding.ASCII.GetBytes("qjzqo^");
Action action = () => filter.Decode(bytes, new PdfDictionary(), 0); Action action = () => filter.Decode(bytes, dictionary, 0);
Assert.Throws<InvalidOperationException>(action); Assert.Throws<InvalidOperationException>(action);
} }
@@ -57,7 +60,7 @@ O<DJ+*.@<*K0@<6L(Df-\0Ec5e;DffZ(EZee.Bl.9pF""AGXBPCsi + DGm >@3BB / F * &OCAfu2
{ {
var bytes = Encoding.ASCII.GetBytes("9jqo^B"); var bytes = Encoding.ASCII.GetBytes("9jqo^B");
Action action = () => filter.Decode(bytes, new PdfDictionary(), 1); Action action = () => filter.Decode(bytes, dictionary, 1);
Assert.Throws<ArgumentOutOfRangeException>(action); Assert.Throws<ArgumentOutOfRangeException>(action);
} }
@@ -102,7 +105,7 @@ T()<(%'A;f?Ma+CT;%+E_a:A0>K&EZek1D/aN,F)u&6DBNA*A0>f4BOu4*+EM76E,9eK+B3(_<%9""p.
F*22=@:F%a+=SF4C'moi+=Li?EZeh0FD)e-@<>p#@;]TuBl.9kATKCFGA(],AKYo5BOu4*+CT;%+C#7pF_Pr+@VfTuDf0B:+=SF4C'moi+= F*22=@:F%a+=SF4C'moi+=Li?EZeh0FD)e-@<>p#@;]TuBl.9kATKCFGA(],AKYo5BOu4*+CT;%+C#7pF_Pr+@VfTuDf0B:+=SF4C'moi+=
Li?EZek1DKKT1F`2DD/TboKAKY](@:s.m/h%oBC'mC/$>""*cF*)G6@;Q?_DIdZpC&~>"; Li?EZek1DKKT1F`2DD/TboKAKY](@:s.m/h%oBC'mC/$>""*cF*)G6@;Q?_DIdZpC&~>";
var result = filter.Decode(Encoding.ASCII.GetBytes(input), new PdfDictionary(), 0); var result = filter.Decode(Encoding.ASCII.GetBytes(input), dictionary, 0);
var text = Encoding.ASCII.GetString(result); var text = Encoding.ASCII.GetString(result);
@@ -122,7 +125,7 @@ T()<(%'A;f?Ma+CT;%+E_a:A0>K&EZek1D/aN,F)u&6DBNA*A0>f4BOu4*+EM76E,9eK+B3(_<%9""p.
F*22=@:F%a+=SF4C'moi+=Li?EZeh0FD)e-@<>p#@;]TuBl.9kATKCFGA(],AKYo5BOu4*+CT;%+C#7pF_Pr+@VfTuDf0B:+=SF4C'moi+= F*22=@:F%a+=SF4C'moi+=Li?EZeh0FD)e-@<>p#@;]TuBl.9kATKCFGA(],AKYo5BOu4*+CT;%+C#7pF_Pr+@VfTuDf0B:+=SF4C'moi+=
Li?EZek1DKKT1F`2DD/TboKAKY](@:s.m/h%oBC'mC/$>""*cF*)G6@;Q?_DIdZpC&"; Li?EZek1DKKT1F`2DD/TboKAKY](@:s.m/h%oBC'mC/$>""*cF*)G6@;Q?_DIdZpC&";
var result = filter.Decode(Encoding.ASCII.GetBytes(input), new PdfDictionary(), 0); var result = filter.Decode(Encoding.ASCII.GetBytes(input), dictionary, 0);
var text = Encoding.ASCII.GetString(result); var text = Encoding.ASCII.GetString(result);

View File

@@ -1,13 +1,16 @@
namespace UglyToad.PdfPig.Tests.Filters namespace UglyToad.PdfPig.Tests.Filters
{ {
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using PdfPig.ContentStream;
using PdfPig.Filters; using PdfPig.Filters;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
public class AsciiHexDecodeFilterTests public class AsciiHexDecodeFilterTests
{ {
private readonly DictionaryToken dictionary = new DictionaryToken(new Dictionary<IToken, IToken>());
[Fact] [Fact]
public void DecodesEncodedTextProperly() public void DecodesEncodedTextProperly()
{ {
@@ -16,7 +19,7 @@
var input = Encoding.ASCII.GetBytes( var input = Encoding.ASCII.GetBytes(
"7368652073656C6C73207365617368656C6C73206F6E20746865207365612073686F7265"); "7368652073656C6C73207365617368656C6C73206F6E20746865207365612073686F7265");
var decoded = new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); var decoded = new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
var decodedText = Encoding.ASCII.GetString(decoded); var decodedText = Encoding.ASCII.GetString(decoded);
@@ -31,7 +34,7 @@
var input = Encoding.ASCII.GetBytes( var input = Encoding.ASCII.GetBytes(
"<7368652073656C6C73207365617368656C6C73206F6E20746865207365612073686F7265>"); "<7368652073656C6C73207365617368656C6C73206F6E20746865207365612073686F7265>");
var decoded = new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); var decoded = new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
var decodedText = Encoding.ASCII.GetString(decoded); var decodedText = Encoding.ASCII.GetString(decoded);
@@ -47,7 +50,7 @@
@"6F6E6365207 5706F6E206120 74696D6520696E @"6F6E6365207 5706F6E206120 74696D6520696E
20612067616C6178792046617220466172204177 6179"); 20612067616C6178792046617220466172204177 6179");
var decoded = new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); var decoded = new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
var decodedText = Encoding.ASCII.GetString(decoded); var decodedText = Encoding.ASCII.GetString(decoded);
@@ -61,7 +64,7 @@
var input = Encoding.ASCII.GetBytes("6f6e63652075706f6e20612074696d6520696e20612067616c61787920466172204661722041776179"); var input = Encoding.ASCII.GetBytes("6f6e63652075706f6e20612074696d6520696e20612067616c61787920466172204661722041776179");
var decoded = new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); var decoded = new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
var decodedText = Encoding.ASCII.GetString(decoded); var decodedText = Encoding.ASCII.GetString(decoded);
@@ -75,7 +78,7 @@
{ {
var input = Encoding.ASCII.GetBytes(inputString); var input = Encoding.ASCII.GetBytes(inputString);
Action action = () => new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); Action action = () => new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
Assert.Throws<InvalidOperationException>(action); Assert.Throws<InvalidOperationException>(action);
} }
@@ -85,7 +88,7 @@
{ {
var input = Encoding.ASCII.GetBytes("AE5>"); var input = Encoding.ASCII.GetBytes("AE5>");
var decoded = new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); var decoded = new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
var decodedText = Encoding.UTF7.GetString(decoded); var decodedText = Encoding.UTF7.GetString(decoded);
@@ -99,7 +102,7 @@
var input = Encoding.ASCII.GetBytes("6f6e63652075706f6e20612074696d6520696e20612067616c61787920466172204661722041776179> There is stuff following the EOD."); var input = Encoding.ASCII.GetBytes("6f6e63652075706f6e20612074696d6520696e20612067616c61787920466172204661722041776179> There is stuff following the EOD.");
var decoded = new AsciiHexDecodeFilter().Decode(input, new PdfDictionary(), 1); var decoded = new AsciiHexDecodeFilter().Decode(input, dictionary, 1);
var decodedText = Encoding.ASCII.GetString(decoded); var decodedText = Encoding.ASCII.GetString(decoded);

View File

@@ -1,9 +1,10 @@
namespace UglyToad.PdfPig.Tests.Filters namespace UglyToad.PdfPig.Tests.Filters
{ {
using System; using System;
using System.Collections.Generic;
using Parser.Parts; using Parser.Parts;
using PdfPig.ContentStream;
using PdfPig.Filters; using PdfPig.Filters;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
public class DecodeParameterResolverTests public class DecodeParameterResolverTests
@@ -21,7 +22,7 @@
[Fact] [Fact]
public void NegativeIndex_Throws() public void NegativeIndex_Throws()
{ {
Action action = () => resolver.GetFilterParameters(new PdfDictionary(), -1); Action action = () => resolver.GetFilterParameters(new DictionaryToken(new Dictionary<IToken, IToken>()), -1);
Assert.Throws<ArgumentOutOfRangeException>(action); Assert.Throws<ArgumentOutOfRangeException>(action);
} }
@@ -29,9 +30,9 @@
[Fact] [Fact]
public void EmptyDictionary_ReturnsEmptyDictionary() public void EmptyDictionary_ReturnsEmptyDictionary()
{ {
var result = resolver.GetFilterParameters(new PdfDictionary(), 0); var result = resolver.GetFilterParameters(new DictionaryToken(new Dictionary<IToken, IToken>()), 0);
Assert.Empty(result); Assert.Empty(result.Data);
} }
} }
} }

View File

@@ -1,7 +1,8 @@
namespace UglyToad.PdfPig.Tests.Filters namespace UglyToad.PdfPig.Tests.Filters
{ {
using PdfPig.ContentStream; using System.Collections.Generic;
using PdfPig.Filters; using PdfPig.Filters;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
public class RunLengthFilterTests public class RunLengthFilterTests
@@ -25,7 +26,7 @@
1, 10, 19 1, 10, 19
}; };
var decoded = filter.Decode(data, new PdfDictionary(), 1); var decoded = filter.Decode(data, new DictionaryToken(new Dictionary<IToken, IToken>()), 1);
var expectedResult = new byte[] var expectedResult = new byte[]
{ {
@@ -54,7 +55,7 @@
90, 6, 7 90, 6, 7
}; };
var decoded = filter.Decode(data, new PdfDictionary(), 0); var decoded = filter.Decode(data, new DictionaryToken(new Dictionary<IToken, IToken>()), 0);
var expectedResult = new byte[] var expectedResult = new byte[]
{ {

View File

@@ -1,13 +1,13 @@
namespace UglyToad.PdfPig.Tests.Graphics.Operations.TextState namespace UglyToad.PdfPig.Tests.Graphics.Operations.TextState
{ {
using System; using System;
using PdfPig.Cos;
using PdfPig.Graphics.Operations.TextState; using PdfPig.Graphics.Operations.TextState;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
public class SetFontAndSizeTests public class SetFontAndSizeTests
{ {
private static readonly CosName Font1Name = CosName.Create("Font1"); private static readonly NameToken Font1Name = NameToken.Create("Font1");
[Fact] [Fact]
public void HasCorrectSymbol() public void HasCorrectSymbol()
@@ -22,7 +22,7 @@
{ {
var setFontAndSize = new SetFontAndSize(Font1Name, 12.75m); var setFontAndSize = new SetFontAndSize(Font1Name, 12.75m);
Assert.Equal("Font1", setFontAndSize.Font.Name); Assert.Equal("Font1", setFontAndSize.Font.Data);
Assert.Equal(12.75m, setFontAndSize.Size); Assert.Equal(12.75m, setFontAndSize.Size);
} }

View File

@@ -3,8 +3,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Content; using Content;
using IO; using IO;
using PdfPig.ContentStream;
using PdfPig.Cos;
using PdfPig.Fonts; using PdfPig.Fonts;
using PdfPig.Graphics; using PdfPig.Graphics;
using PdfPig.Tokenization.Tokens; using PdfPig.Tokenization.Tokens;
@@ -50,11 +48,11 @@
internal class TestResourceStore : IResourceStore internal class TestResourceStore : IResourceStore
{ {
public void LoadResourceDictionary(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) public void LoadResourceDictionary(DictionaryToken dictionary, bool isLenientParsing)
{ {
} }
public IFont GetFont(CosName name) public IFont GetFont(NameToken name)
{ {
return null; return null;
} }

View File

@@ -6,9 +6,8 @@
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using PdfPig.ContentStream;
using PdfPig.Cos;
using PdfPig.Filters; using PdfPig.Filters;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
/* /*
@@ -88,16 +87,21 @@
var endStreamPosition = GetOffset(bytes, "endstream", streamPosition.end); var endStreamPosition = GetOffset(bytes, "endstream", streamPosition.end);
var streamBytes = BytesBetween(streamPosition.end + 1, endStreamPosition.start - 1, bytes); var streamBytes = BytesBetween(streamPosition.end + 1, endStreamPosition.start - 1, bytes);
var paramsDict = new PdfDictionary();
paramsDict.Set(CosName.PREDICTOR, new CosFloat("12"));
paramsDict.Set(CosName.COLUMNS, new CosFloat("4"));
var dict = new PdfDictionary(); var paramsDict = new DictionaryToken(new Dictionary<IToken, IToken>
dict.Set(CosName.FILTER, CosName.FLATE_DECODE); {
dict.Set(CosName.DECODE_PARMS, paramsDict); { NameToken.Predictor, new NumericToken(12) },
{ NameToken.Columns, new NumericToken(4) }
});
var dictionary = new DictionaryToken(new Dictionary<IToken, IToken>
{
{NameToken.Filter, NameToken.FlateDecode},
{NameToken.DecodeParms, paramsDict}
});
var filter = new FlateFilter(new DecodeParameterResolver(null), new PngPredictor(), null); var filter = new FlateFilter(new DecodeParameterResolver(null), new PngPredictor(), null);
var filtered = filter.Decode(streamBytes, dict, 0); var filtered = filter.Decode(streamBytes, dictionary, 0);
var expected = var expected =
"1 0 15 0 1 0 216 0 1 2 160 0 1 2 210 0 1 3 84 0 1 4 46 0 1 7 165 0 1 70 229 0 1 72 84 0 1 96 235 0 1 98 18 0 2 0 12 0 2 0 12 1 2 0 12 2 2 0 12 3 2 0 12 4 2 0 12 5 2 0 12 6 2 0 12 7 2 0 12 8" "1 0 15 0 1 0 216 0 1 2 160 0 1 2 210 0 1 3 84 0 1 4 46 0 1 7 165 0 1 70 229 0 1 72 84 0 1 96 235 0 1 98 18 0 2 0 12 0 2 0 12 1 2 0 12 2 2 0 12 3 2 0 12 4 2 0 12 5 2 0 12 6 2 0 12 7 2 0 12 8"

View File

@@ -1,6 +1,5 @@
namespace UglyToad.PdfPig.Tests.Parser namespace UglyToad.PdfPig.Tests.Parser
{ {
using PdfPig.Cos;
using PdfPig.Graphics; using PdfPig.Graphics;
using PdfPig.Graphics.Core; using PdfPig.Graphics.Core;
using PdfPig.Graphics.Operations.General; using PdfPig.Graphics.Operations.General;
@@ -9,6 +8,7 @@
using PdfPig.Graphics.Operations.TextShowing; using PdfPig.Graphics.Operations.TextShowing;
using PdfPig.Graphics.Operations.TextState; using PdfPig.Graphics.Operations.TextState;
using PdfPig.Parser; using PdfPig.Parser;
using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
public class PageContentParserTests public class PageContentParserTests
@@ -42,7 +42,7 @@ ET";
Assert.Equal(BeginText.Value, result[0]); Assert.Equal(BeginText.Value, result[0]);
var font = Assert.IsType<SetFontAndSize>(result[1]); var font = Assert.IsType<SetFontAndSize>(result[1]);
Assert.Equal(CosName.Create("F13"), font.Font); Assert.Equal(NameToken.Create("F13"), font.Font);
Assert.Equal(48, font.Size); Assert.Equal(48, font.Size);
var nextLine = Assert.IsType<MoveToNextLineWithOffset>(result[2]); var nextLine = Assert.IsType<MoveToNextLineWithOffset>(result[2]);

View File

@@ -1,7 +1,6 @@
namespace UglyToad.PdfPig.Tests.Tokenization namespace UglyToad.PdfPig.Tests.Tokenization
{ {
using System.Collections.Generic; using System.Collections.Generic;
using PdfPig.Cos;
using PdfPig.Tokenization; using PdfPig.Tokenization;
using PdfPig.Tokenization.Tokens; using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
@@ -85,12 +84,12 @@
Assert.Equal(12m, AssertDataToken<NumericToken, decimal>(0, array).Data); Assert.Equal(12m, AssertDataToken<NumericToken, decimal>(0, array).Data);
Assert.Equal(10.453m, AssertDataToken<NumericToken, decimal>(1, array).Data); Assert.Equal(10.453m, AssertDataToken<NumericToken, decimal>(1, array).Data);
Assert.Equal(CosName.Create("Fonts"), AssertDataToken<NameToken, CosName>(2, array).Data); Assert.Equal(NameToken.Create("Fonts"), AssertDataToken<NameToken, string>(2, array).Data);
var inner = AssertArrayToken(array.Data[3]); var inner = AssertArrayToken(array.Data[3]);
Assert.Equal(CosName.Create("F1"), AssertDataToken<NameToken, CosName>(0, inner).Data); Assert.Equal(NameToken.Create("F1"), AssertDataToken<NameToken, string>(0, inner).Data);
Assert.Equal(CosName.Create("F3"), AssertDataToken<NameToken, CosName>(1, inner).Data); Assert.Equal(NameToken.Create("F3"), AssertDataToken<NameToken, string>(1, inner).Data);
Assert.Equal("Moreover", AssertDataToken<StringToken, string>(4, array).Data); Assert.Equal("Moreover", AssertDataToken<StringToken, string>(4, array).Data);
} }
@@ -108,7 +107,7 @@
var array = AssertArrayToken(token); var array = AssertArrayToken(token);
Assert.Equal(CosName.Create("Bounds"), AssertDataToken<NameToken, CosName>(0, array).Data); Assert.Equal(NameToken.Create("Bounds"), AssertDataToken<NameToken, string>(0, array).Data);
var firstInner = AssertArrayToken(array.Data[1]); var firstInner = AssertArrayToken(array.Data[1]);
@@ -150,7 +149,7 @@
Assert.Equal(3.14m, AssertDataToken<NumericToken, decimal>(1, array).Data); Assert.Equal(3.14m, AssertDataToken<NumericToken, decimal>(1, array).Data);
Assert.False(AssertDataToken<BooleanToken, bool>(2, array).Data); Assert.False(AssertDataToken<BooleanToken, bool>(2, array).Data);
Assert.Equal("Ralph", AssertDataToken<StringToken, string>(3, array).Data); Assert.Equal("Ralph", AssertDataToken<StringToken, string>(3, array).Data);
Assert.Equal(CosName.Create("SomeName"), AssertDataToken<NameToken, CosName>(4, array).Data); Assert.Equal(NameToken.Create("SomeName"), AssertDataToken<NameToken, string>(4, array).Data);
} }
private static ArrayToken AssertArrayToken(IToken token) private static ArrayToken AssertArrayToken(IToken token)

View File

@@ -4,7 +4,6 @@ namespace UglyToad.PdfPig.Tests.Tokenization
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using PdfPig.ContentStream; using PdfPig.ContentStream;
using PdfPig.Cos;
using PdfPig.Tokenization; using PdfPig.Tokenization;
using PdfPig.Tokenization.Tokens; using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
@@ -39,7 +38,7 @@ namespace UglyToad.PdfPig.Tests.Tokenization
var dictionary = AssertDictionaryToken(token); var dictionary = AssertDictionaryToken(token);
AssertDictionaryEntry<StringToken, string>(dictionary, CosName.NAME, "Barry Scott"); AssertDictionaryEntry<StringToken, string>(dictionary, NameToken.Name, "Barry Scott");
} }
[Fact] [Fact]
@@ -53,8 +52,7 @@ namespace UglyToad.PdfPig.Tests.Tokenization
var dictionary = AssertDictionaryToken(token); var dictionary = AssertDictionaryToken(token);
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.TYPE, AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Type, "Example");
CosName.Create("Example"));
} }
[Fact] [Fact]
@@ -68,9 +66,9 @@ namespace UglyToad.PdfPig.Tests.Tokenization
var dictionary = AssertDictionaryToken(token); var dictionary = AssertDictionaryToken(token);
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.FILTER, CosName.FLATE_DECODE); AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Filter, NameToken.FlateDecode.Data);
AssertDictionaryEntry<NumericToken, decimal>(dictionary, CosName.S, 36); AssertDictionaryEntry<NumericToken, decimal>(dictionary, NameToken.S, 36);
AssertDictionaryEntry<NumericToken, decimal>(dictionary, CosName.LENGTH, 53); AssertDictionaryEntry<NumericToken, decimal>(dictionary, NameToken.Length, 53);
} }
[Fact] [Fact]
@@ -86,8 +84,8 @@ namespace UglyToad.PdfPig.Tests.Tokenization
var reference = new IndirectReference(14, 0); var reference = new IndirectReference(14, 0);
AssertDictionaryEntry<IndirectReferenceToken, IndirectReference>(dictionary, CosName.PAGES, reference); AssertDictionaryEntry<IndirectReferenceToken, IndirectReference>(dictionary, NameToken.Pages, reference);
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.TYPE, CosName.CATALOG); AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Type, NameToken.Catalog);
} }
[Fact] [Fact]
@@ -114,11 +112,11 @@ namespace UglyToad.PdfPig.Tests.Tokenization
var dictionary = AssertDictionaryToken(token); var dictionary = AssertDictionaryToken(token);
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.TYPE, CosName.Create("Example")); AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Type, "Example");
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.SUBTYPE, CosName.Create("DictionaryExample")); AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Subtype, "DictionaryExample");
AssertDictionaryEntry<NumericToken, decimal>(dictionary, CosName.VERSION, 0.01m); AssertDictionaryEntry<NumericToken, decimal>(dictionary, NameToken.Version, 0.01m);
AssertDictionaryEntry<NumericToken, decimal>(dictionary, CosName.Create("IntegerItem"), 12m); AssertDictionaryEntry<NumericToken, decimal>(dictionary, NameToken.Create("IntegerItem"), 12m);
AssertDictionaryEntry<StringToken, string>(dictionary, CosName.Create("StringItem"), "a string"); AssertDictionaryEntry<StringToken, string>(dictionary, NameToken.Create("StringItem"), "a string");
var subDictionary = GetIndex(5, dictionary); var subDictionary = GetIndex(5, dictionary);
@@ -126,10 +124,10 @@ namespace UglyToad.PdfPig.Tests.Tokenization
var subDictionaryValue = Assert.IsType<DictionaryToken>(subDictionary.Value); var subDictionaryValue = Assert.IsType<DictionaryToken>(subDictionary.Value);
AssertDictionaryEntry<NumericToken, decimal>(subDictionaryValue, CosName.Create("Item1"), 0.4m); AssertDictionaryEntry<NumericToken, decimal>(subDictionaryValue, NameToken.Create("Item1"), 0.4m);
AssertDictionaryEntry<BooleanToken, bool>(subDictionaryValue, CosName.Create("Item2"), true); AssertDictionaryEntry<BooleanToken, bool>(subDictionaryValue, NameToken.Create("Item2"), true);
AssertDictionaryEntry<StringToken, string>(subDictionaryValue, CosName.Create("LastItem"), "not!"); AssertDictionaryEntry<StringToken, string>(subDictionaryValue, NameToken.Create("LastItem"), "not!");
AssertDictionaryEntry<StringToken, string>(subDictionaryValue, CosName.Create("VeryLastItem"), "OK"); AssertDictionaryEntry<StringToken, string>(subDictionaryValue, NameToken.Create("VeryLastItem"), "OK");
} }
[Fact] [Fact]
@@ -147,8 +145,8 @@ endobj
var reference = new IndirectReference(69, 0); var reference = new IndirectReference(69, 0);
AssertDictionaryEntry<IndirectReferenceToken, IndirectReference>(dictionary, CosName.PAGES, reference); AssertDictionaryEntry<IndirectReferenceToken, IndirectReference>(dictionary, NameToken.Pages, reference);
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.TYPE, CosName.CATALOG); AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Type, NameToken.Catalog.Data);
Assert.Equal(2, dictionary.Data.Count); Assert.Equal(2, dictionary.Data.Count);
} }
@@ -164,7 +162,7 @@ endobj
var dictionary = AssertDictionaryToken(token); var dictionary = AssertDictionaryToken(token);
AssertDictionaryEntry<NumericToken, decimal>(dictionary, CosName.COUNT, 12); AssertDictionaryEntry<NumericToken, decimal>(dictionary, NameToken.Count, 12);
var subDictionaryToken = GetIndex(1, dictionary); var subDictionaryToken = GetIndex(1, dictionary);
@@ -172,17 +170,17 @@ endobj
var subDictionary = Assert.IsType<DictionaryToken>(subDictionaryToken.Value); var subDictionary = Assert.IsType<DictionaryToken>(subDictionaryToken.Value);
AssertDictionaryEntry<StringToken, string>(subDictionary, CosName.NAME, "Glorp"); AssertDictionaryEntry<StringToken, string>(subDictionary, NameToken.Name, "Glorp");
AssertDictionaryEntry<NameToken, CosName>(dictionary, CosName.TYPE, CosName.CATALOG); AssertDictionaryEntry<NameToken, string>(dictionary, NameToken.Type, NameToken.Catalog.Data);
Assert.Equal(3, dictionary.Data.Count); Assert.Equal(3, dictionary.Data.Count);
} }
private static void AssertDictionaryEntry<TValue, TValueData>(DictionaryToken dictionary, CosName key, private static void AssertDictionaryEntry<TValue, TValueData>(DictionaryToken dictionary, NameToken key,
TValueData value) where TValue : IDataToken<TValueData> TValueData value) where TValue : IDataToken<TValueData>
{ {
var result = dictionary.Data[key.Name]; var result = dictionary.Data[key.Data];
var valueToken = Assert.IsType<TValue>(result); var valueToken = Assert.IsType<TValue>(result);

View File

@@ -19,7 +19,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("Type", AssertNameToken(token).Data.Name); Assert.Equal("Type", AssertNameToken(token).Data);
} }
[Fact] [Fact]
@@ -33,7 +33,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("Type", AssertNameToken(token).Data.Name); Assert.Equal("Type", AssertNameToken(token).Data);
} }
[Fact] [Fact]
@@ -59,7 +59,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("XRef", AssertNameToken(token).Data.Name); Assert.Equal("XRef", AssertNameToken(token).Data);
} }
[Fact] [Fact]
@@ -73,7 +73,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("Priorto1.2#INvalidHexHash", AssertNameToken(token).Data.Name); Assert.Equal("Priorto1.2#INvalidHexHash", AssertNameToken(token).Data);
} }
[Theory] [Theory]
@@ -92,7 +92,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal(expected, AssertNameToken(token).Data.Name); Assert.Equal(expected, AssertNameToken(token).Data);
} }
[Theory] [Theory]
@@ -109,7 +109,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal(expected, AssertNameToken(token).Data.Name); Assert.Equal(expected, AssertNameToken(token).Data);
} }
[Fact] [Fact]
@@ -121,7 +121,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("Invalid#AZBadHex", AssertNameToken(token).Data.Name); Assert.Equal("Invalid#AZBadHex", AssertNameToken(token).Data);
} }
[Fact] [Fact]
@@ -133,7 +133,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("Invalid#Z", AssertNameToken(token).Data.Name); Assert.Equal("Invalid#Z", AssertNameToken(token).Data);
} }
[Fact] [Fact]
@@ -145,7 +145,7 @@
Assert.True(result); Assert.True(result);
Assert.Equal("Hex#", AssertNameToken(token).Data.Name); Assert.Equal("Hex#", AssertNameToken(token).Data);
} }
private static NameToken AssertNameToken(IToken token) private static NameToken AssertNameToken(IToken token)

View File

@@ -4,7 +4,6 @@ namespace UglyToad.PdfPig.Tests.Tokenization.Scanner
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using IO; using IO;
using PdfPig.Cos;
using PdfPig.Tokenization.Scanner; using PdfPig.Tokenization.Scanner;
using PdfPig.Tokenization.Tokens; using PdfPig.Tokenization.Tokens;
using Xunit; using Xunit;
@@ -36,7 +35,7 @@ namespace UglyToad.PdfPig.Tests.Tokenization.Scanner
AssertCorrectToken<NumericToken, decimal>(tokens[1], 3.14m); AssertCorrectToken<NumericToken, decimal>(tokens[1], 3.14m);
AssertCorrectToken<BooleanToken, bool>(tokens[2], false); AssertCorrectToken<BooleanToken, bool>(tokens[2], false);
AssertCorrectToken<StringToken, string>(tokens[3], "Ralph"); AssertCorrectToken<StringToken, string>(tokens[3], "Ralph");
AssertCorrectToken<NameToken, CosName>(tokens[4], CosName.Create("SomeName")); AssertCorrectToken<NameToken, string>(tokens[4], "SomeName");
} }
[Fact] [Fact]
@@ -57,15 +56,15 @@ namespace UglyToad.PdfPig.Tests.Tokenization.Scanner
tokens.Add(scanner.CurrentToken); tokens.Add(scanner.CurrentToken);
} }
AssertCorrectToken<NameToken, CosName>(tokens[0], CosName.TYPE); AssertCorrectToken<NameToken, string>(tokens[0], NameToken.Type.Data);
AssertCorrectToken<NameToken, CosName>(tokens[1], CosName.Create("Example")); AssertCorrectToken<NameToken, string>(tokens[1], "Example");
AssertCorrectToken<NameToken, CosName>(tokens[2], CosName.SUBTYPE); AssertCorrectToken<NameToken, string>(tokens[2], NameToken.Subtype.Data);
AssertCorrectToken<NameToken, CosName>(tokens[3], CosName.Create("DictionaryExample")); AssertCorrectToken<NameToken, string>(tokens[3], "DictionaryExample");
AssertCorrectToken<NameToken, CosName>(tokens[4], CosName.VERSION); AssertCorrectToken<NameToken, string>(tokens[4], NameToken.Version.Data);
AssertCorrectToken<NumericToken, decimal>(tokens[5], 0.01m); AssertCorrectToken<NumericToken, decimal>(tokens[5], 0.01m);
AssertCorrectToken<NameToken, CosName>(tokens[6], CosName.Create("IntegerItem")); AssertCorrectToken<NameToken, string>(tokens[6], "IntegerItem");
AssertCorrectToken<NumericToken, decimal>(tokens[7], 12m); AssertCorrectToken<NumericToken, decimal>(tokens[7], 12m);
AssertCorrectToken<NameToken, CosName>(tokens[8], CosName.Create("StringItem")); AssertCorrectToken<NameToken, string>(tokens[8], "StringItem");
AssertCorrectToken<StringToken, string>(tokens[9], "a string"); AssertCorrectToken<StringToken, string>(tokens[9], "a string");
} }
@@ -106,11 +105,11 @@ endobj";
tokens.Add(scanner.CurrentToken); tokens.Add(scanner.CurrentToken);
} }
AssertCorrectToken<NameToken, CosName>(tokens[0], CosName.Create("Bounds")); AssertCorrectToken<NameToken, string>(tokens[0], "Bounds");
Assert.IsType<ArrayToken>(tokens[1]); Assert.IsType<ArrayToken>(tokens[1]);
AssertCorrectToken<NameToken, CosName>(tokens[2], CosName.Create("Font")); AssertCorrectToken<NameToken, string>(tokens[2], "Font");
AssertCorrectToken<NameToken, CosName>(tokens[3], CosName.Create("F1")); AssertCorrectToken<NameToken, string>(tokens[3], "F1");
AssertCorrectToken<NameToken, CosName>(tokens[4], CosName.Create("Name")); AssertCorrectToken<NameToken, string>(tokens[4], "Name");
AssertCorrectToken<StringToken, string>(tokens[5], "Bob"); AssertCorrectToken<StringToken, string>(tokens[5], "Bob");
Assert.IsType<ArrayToken>(tokens[6]); Assert.IsType<ArrayToken>(tokens[6]);
} }

View File

@@ -26,7 +26,7 @@
var name = Assert.IsType<NameToken>(objectToken.Data); var name = Assert.IsType<NameToken>(objectToken.Data);
Assert.Equal(294, objectToken.Number.ObjectNumber); Assert.Equal(294, objectToken.Number.ObjectNumber);
Assert.Equal(0, objectToken.Number.Generation); Assert.Equal(0, objectToken.Number.Generation);
Assert.Equal("WDKAAR+CMBX12", name.Data); Assert.Equal("WDKAAR+CMBX12", name.Data);
@@ -126,7 +126,7 @@ endobj
/Type /Pages /Type /Pages
/Count 2 /Count 2
/Parent 275 0 R /Parent 275 0 R
/Kids [ 121 0 R 125 0 R ] /Kids [ 121 0 R 125 0 R ]
>> >>
endobj endobj
@@ -275,6 +275,34 @@ endobj";
var scanner = GetScanner(s, locationProvider); var scanner = GetScanner(s, locationProvider);
var token = ReadToEnd(scanner)[1]; var token = ReadToEnd(scanner)[1];
var stream = Assert.IsType<StreamToken>(token.Data);
Assert.Equal(52, stream.Data.Length);
var outputString = Encoding.UTF8.GetString(stream.Data);
Assert.Equal("%¥×³®í»š}%§X{{tøNåÝž¶ö¢ÖÞ¾~´¼", outputString);
}
[Fact]
public void ReadsStreamWithMissingLength()
{
const string s = @"
12655 0 obj
<< /S 1245 >>
stream
%¥×³®í»š}%§X{{tøNåÝž¶ö¢ÖÞgrehtyyy$&%&£$££(*¾–~´¼
endstream
endobj";
var scanner = GetScanner(s);
var token = ReadToEnd(scanner)[0];
Assert.Equal(12655, token.Number.ObjectNumber);
var stream = Assert.IsType<StreamToken>(token.Data); var stream = Assert.IsType<StreamToken>(token.Data);

View File

@@ -1,13 +0,0 @@
namespace UglyToad.PdfPig.Tests.Tokenization
{
using Xunit;
public class StreamTokenizerTests
{
[Fact]
public void ReadsStream()
{
}
}
}

View File

@@ -59,7 +59,7 @@
var transform = streamBytes; var transform = streamBytes;
for (var i = 0; i < filters.Count; i++) for (var i = 0; i < filters.Count; i++)
{ {
transform = filters[i].Decode(transform, Dictionary, i); //transform = filters[i].Decode(transform, Dictionary, i);
} }
decodedBytes = transform; decodedBytes = transform;

View File

@@ -1,6 +1,6 @@
namespace UglyToad.PdfPig.Fonts namespace UglyToad.PdfPig.Fonts
{ {
using ContentStream; using Tokenization.Tokens;
/// <summary> /// <summary>
/// The bytes of the stream containing the font program. /// The bytes of the stream containing the font program.
@@ -13,13 +13,13 @@
/// </remarks> /// </remarks>
internal class DescriptorFontFile internal class DescriptorFontFile
{ {
public IndirectReference ObjectKey { get; } public IndirectReferenceToken ObjectKey { get; }
public byte[] FileBytes { get; } public byte[] FileBytes { get; }
public FontFileType FileType { get; } public FontFileType FileType { get; }
public DescriptorFontFile(IndirectReference key, FontFileType fileType) public DescriptorFontFile(IndirectReferenceToken key, FontFileType fileType)
{ {
ObjectKey = key; ObjectKey = key;
FileBytes = new byte[0]; FileBytes = new byte[0];

View File

@@ -2,7 +2,7 @@
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Cos; using Tokenization.Tokens;
/// <summary> /// <summary>
/// Maps character codes to glyph names from a PostScript encoding. /// Maps character codes to glyph names from a PostScript encoding.
@@ -57,7 +57,7 @@
} }
} }
public static bool TryGetNamedEncoding(CosName name, out Encoding encoding) public static bool TryGetNamedEncoding(NameToken name, out Encoding encoding)
{ {
encoding = null; encoding = null;
@@ -66,25 +66,25 @@
return false; return false;
} }
if (name.Equals(CosName.STANDARD_ENCODING)) if (name.Equals(NameToken.StandardEncoding))
{ {
encoding = StandardEncoding.Instance; encoding = StandardEncoding.Instance;
return true; return true;
} }
if (name.Equals(CosName.WIN_ANSI_ENCODING)) if (name.Equals(NameToken.WinAnsiEncoding))
{ {
encoding = WinAnsiEncoding.Instance; encoding = WinAnsiEncoding.Instance;
return true; return true;
} }
if (name.Equals(CosName.MAC_EXPERT_ENCODING)) if (name.Equals(NameToken.MacExpertEncoding))
{ {
encoding = MacExpertEncoding.Instance; encoding = MacExpertEncoding.Instance;
return true; return true;
} }
if (name.Equals(CosName.MAC_ROMAN_ENCODING)) if (name.Equals(NameToken.MacRomanEncoding))
{ {
encoding = MacRomanEncoding.Instance; encoding = MacRomanEncoding.Instance;
return true; return true;

View File

@@ -1,7 +1,7 @@
namespace UglyToad.PdfPig.Fonts namespace UglyToad.PdfPig.Fonts
{ {
using Cos;
using Geometry; using Geometry;
using Tokenization.Tokens;
using Util.JetBrains.Annotations; using Util.JetBrains.Annotations;
/// <summary> /// <summary>
@@ -26,7 +26,7 @@
/// The PostScript name for the font. /// The PostScript name for the font.
/// </summary> /// </summary>
/// <remarks>Required</remarks> /// <remarks>Required</remarks>
public CosName FontName { get; } public NameToken FontName { get; }
/// <summary> /// <summary>
/// The preferred font family. /// The preferred font family.
@@ -155,7 +155,7 @@
[CanBeNull] [CanBeNull]
public string CharSet { get; set; } public string CharSet { get; set; }
public FontDescriptor(CosName name, FontFlags flags) public FontDescriptor(NameToken name, FontFlags flags)
{ {
FontName = name; FontName = name;
Flags = flags; Flags = flags;

View File

@@ -1,12 +1,12 @@
namespace UglyToad.PdfPig.Fonts namespace UglyToad.PdfPig.Fonts
{ {
using Cos; using Tokenization.Tokens;
internal static class FontStretchExtensions internal static class FontStretchExtensions
{ {
public static FontStretch ConvertToFontStretch(this CosName name) public static FontStretch ConvertToFontStretch(this NameToken name)
{ {
switch (name.Name) switch (name.Data)
{ {
case "UltraCondensed": case "UltraCondensed":
return FontStretch.UltraCondensed; return FontStretch.UltraCondensed;

View File

@@ -1,58 +1,45 @@
namespace UglyToad.PdfPig.Fonts.Parser namespace UglyToad.PdfPig.Fonts.Parser
{ {
using System.Collections.Generic; using System.Collections.Generic;
using ContentStream;
using Cos;
using Encodings; using Encodings;
using Exceptions; using Exceptions;
using IO;
using PdfPig.Parser;
using PdfPig.Parser.Parts; using PdfPig.Parser.Parts;
using Tokenization.Scanner;
using Tokenization.Tokens;
using Util;
internal class EncodingReader : IEncodingReader internal class EncodingReader : IEncodingReader
{ {
private readonly IPdfObjectParser pdfObjectParser; private readonly IPdfObjectScanner pdfScanner;
public EncodingReader(IPdfObjectParser pdfObjectParser) public EncodingReader(IPdfObjectScanner pdfScanner)
{ {
this.pdfObjectParser = pdfObjectParser; this.pdfScanner = pdfScanner;
} }
public Encoding Read(PdfDictionary fontDictionary, IRandomAccessRead reader, bool isLenientParsing, FontDescriptor descriptor = null) public Encoding Read(DictionaryToken fontDictionary, bool isLenientParsing, FontDescriptor descriptor = null)
{ {
if (!fontDictionary.TryGetValue(CosName.ENCODING, out var baseEncodingObject)) if (!fontDictionary.TryGet(NameToken.Encoding, out var baseEncodingObject))
{ {
return null; return null;
} }
if (baseEncodingObject is CosName name) if (baseEncodingObject is NameToken name)
{ {
return GetNamedEncoding(descriptor, name); return GetNamedEncoding(descriptor, name);
} }
PdfDictionary encodingDictionary; DictionaryToken encodingDictionary = DirectObjectFinder.Get<DictionaryToken>(baseEncodingObject, pdfScanner);
if (baseEncodingObject is CosObject reference)
{ var encoding = ReadEncodingDictionary(encodingDictionary);
encodingDictionary = DirectObjectFinder.Find<PdfDictionary>(reference, pdfObjectParser, reader, isLenientParsing);
}
else if (baseEncodingObject is PdfDictionary dictionary)
{
encodingDictionary = dictionary;
}
else
{
throw new InvalidFontFormatException($"The font encoding was not a named entry or dictionary, instead it was: {baseEncodingObject}.");
}
var encoding = ReadEncodingDictionary(encodingDictionary, reader, isLenientParsing);
return encoding; return encoding;
} }
private Encoding ReadEncodingDictionary(PdfDictionary encodingDictionary, IRandomAccessRead reader, bool isLenientParsing) private Encoding ReadEncodingDictionary(DictionaryToken encodingDictionary)
{ {
Encoding baseEncoding; Encoding baseEncoding;
if (encodingDictionary.TryGetName(CosName.BASE_ENCODING, out var baseEncodingName)) if (encodingDictionary.TryGet(NameToken.BaseEncoding, out var baseEncodingToken) && baseEncodingToken is NameToken baseEncodingName)
{ {
if (!Encoding.TryGetNamedEncoding(baseEncodingName, out baseEncoding)) if (!Encoding.TryGetNamedEncoding(baseEncodingName, out baseEncoding))
{ {
@@ -65,23 +52,12 @@
baseEncoding = StandardEncoding.Instance; baseEncoding = StandardEncoding.Instance;
} }
if (!encodingDictionary.TryGetValue(CosName.DIFFERENCES, out var differencesBase)) if (!encodingDictionary.TryGet(NameToken.Differences, out var differencesBase))
{ {
return baseEncoding; return baseEncoding;
} }
var differenceArray = differencesBase as COSArray; var differenceArray = DirectObjectFinder.Get<ArrayToken>(differencesBase, pdfScanner);
if (differenceArray == null)
{
if (differencesBase is CosObject differencesObj)
{
differenceArray = DirectObjectFinder.Find<COSArray>(differencesObj, pdfObjectParser, reader, isLenientParsing);
}
else
{
throw new InvalidFontFormatException($"Differences was not an array: {differencesBase}.");
}
}
var differences = ProcessDifferences(differenceArray); var differences = ProcessDifferences(differenceArray);
@@ -90,22 +66,22 @@
return newEncoding; return newEncoding;
} }
private static IReadOnlyList<(int, string)> ProcessDifferences(COSArray differenceArray) private static IReadOnlyList<(int, string)> ProcessDifferences(ArrayToken differenceArray)
{ {
var activeCode = differenceArray.getInt(0); var activeCode = differenceArray.GetNumeric(0).Int;
var differences = new List<(int, string)>(); var differences = new List<(int, string)>();
for (int i = 1; i < differenceArray.Count; i++) for (int i = 1; i < differenceArray.Data.Count; i++)
{ {
var entry = differenceArray.get(i); var entry = differenceArray.Data[i];
if (entry is ICosNumber numeric) if (entry is NumericToken numeric)
{ {
activeCode = numeric.AsInt(); activeCode = numeric.Int;
} }
else if (entry is CosName name) else if (entry is NameToken name)
{ {
differences.Add((activeCode, name.Name)); differences.Add((activeCode, name.Data));
activeCode++; activeCode++;
} }
else else
@@ -117,7 +93,7 @@
return differences; return differences;
} }
private static Encoding GetNamedEncoding(FontDescriptor descriptor, CosName encodingName) private static Encoding GetNamedEncoding(FontDescriptor descriptor, NameToken encodingName)
{ {
Encoding encoding; Encoding encoding;
// Symbolic fonts default to standard encoding. // Symbolic fonts default to standard encoding.

View File

@@ -1,75 +1,79 @@
namespace UglyToad.PdfPig.Fonts.Parser namespace UglyToad.PdfPig.Fonts.Parser
{ {
using System.Linq;
using ContentStream;
using Cos;
using Exceptions; using Exceptions;
using IO;
using Parts; using Parts;
using PdfPig.Parser;
using PdfPig.Parser.Parts; using PdfPig.Parser.Parts;
using Tokenization.Scanner;
using Tokenization.Tokens;
internal static class FontDictionaryAccessHelper internal static class FontDictionaryAccessHelper
{ {
public static int GetFirstCharacter(PdfDictionary dictionary) public static int GetFirstCharacter(DictionaryToken dictionary)
{ {
if (!dictionary.TryGetItemOfType(CosName.FIRST_CHAR, out CosInt firstChar)) if (!dictionary.TryGet(NameToken.FirstChar, out var firstChar) || !(firstChar is NumericToken number))
{ {
throw new InvalidFontFormatException($"No first character entry was found in the font dictionary for this TrueType font: {dictionary}."); throw new InvalidFontFormatException($"No first character entry was found in the font dictionary for this TrueType font: {dictionary}.");
} }
return firstChar.AsInt(); return number.Int;
} }
public static int GetLastCharacter(PdfDictionary dictionary) public static int GetLastCharacter(DictionaryToken dictionary)
{ {
if (!dictionary.TryGetItemOfType(CosName.LAST_CHAR, out CosInt lastChar)) if (!dictionary.TryGet(NameToken.LastChar, out var firstChar) || !(firstChar is NumericToken number))
{ {
throw new InvalidFontFormatException($"No last character entry was found in the font dictionary for this TrueType font: {dictionary}."); throw new InvalidFontFormatException($"No first character entry was found in the font dictionary for this TrueType font: {dictionary}.");
} }
return lastChar.AsInt(); return number.Int;
} }
public static decimal[] GetWidths(IPdfObjectParser pdfObjectParser, PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) public static decimal[] GetWidths(IPdfObjectScanner pdfScanner, DictionaryToken dictionary, bool isLenientParsing)
{ {
if (!dictionary.TryGetItemOfType(CosName.WIDTHS, out COSArray widthArray)) if (!dictionary.TryGet(NameToken.Widths, out var token))
{ {
if (!dictionary.TryGetItemOfType(CosName.WIDTHS, out CosObject arr)) throw new InvalidFontFormatException($"No widths array found for the font: {dictionary}.");
}
var widthArray = DirectObjectFinder.Get<ArrayToken>(token, pdfScanner);
var result = new decimal[widthArray.Data.Count];
for (int i = 0; i < widthArray.Data.Count; i++)
{
var arrayToken = widthArray.Data[i];
if (!(arrayToken is NumericToken number))
{ {
throw new InvalidFontFormatException($"No widths array was found in the font dictionary for this TrueType font: {dictionary}."); throw new InvalidFontFormatException($"Token which was not a number found in the widths array: {arrayToken}.");
} }
widthArray = DirectObjectFinder.Find<COSArray>(arr, pdfObjectParser, reader, isLenientParsing); result[i] = number.Data;
} }
return widthArray.Select(x => ((ICosNumber)x).AsDecimal()).ToArray(); return result;
} }
public static FontDescriptor GetFontDescriptor(IPdfObjectParser pdfObjectParser, FontDescriptorFactory fontDescriptorFactory, PdfDictionary dictionary, public static FontDescriptor GetFontDescriptor(IPdfObjectScanner pdfScanner, FontDescriptorFactory fontDescriptorFactory, DictionaryToken dictionary,
IRandomAccessRead reader, bool isLenientParsing) bool isLenientParsing)
{ {
if (!dictionary.TryGetItemOfType(CosName.FONT_DESC, out CosObject obj)) if (!dictionary.TryGet(NameToken.FontDesc, out var obj))
{ {
throw new InvalidFontFormatException($"No font descriptor indirect reference found in the TrueType font: {dictionary}."); throw new InvalidFontFormatException($"No font descriptor indirect reference found in the TrueType font: {dictionary}.");
} }
var parsed = pdfObjectParser.Parse(obj.ToIndirectReference(), reader, isLenientParsing); var parsed = DirectObjectFinder.Get<DictionaryToken>(obj, pdfScanner);
if (!(parsed is PdfDictionary descriptorDictionary)) var descriptor = fontDescriptorFactory.Generate(parsed, isLenientParsing);
{
throw new InvalidFontFormatException($"Expected a font descriptor dictionary but instead found {parsed}.");
}
var descriptor = fontDescriptorFactory.Generate(descriptorDictionary, isLenientParsing);
return descriptor; return descriptor;
} }
public static CosName GetName(IPdfObjectParser pdfObjectParser, PdfDictionary dictionary, FontDescriptor descriptor, IRandomAccessRead reader, bool isLenientParsing) public static NameToken GetName(IPdfObjectScanner pdfScanner, DictionaryToken dictionary, FontDescriptor descriptor, bool isLenientParsing)
{ {
if (dictionary.TryGetName(CosName.BASE_FONT, out CosName name)) if (dictionary.TryGet(NameToken.BaseFont, out var nameBase))
{ {
var name = DirectObjectFinder.Get<NameToken>(nameBase, pdfScanner);
return name; return name;
} }
@@ -77,15 +81,7 @@
{ {
return descriptor.FontName; return descriptor.FontName;
} }
if (dictionary.TryGetValue(CosName.BASE_FONT, out var baseFont))
{
if (baseFont is CosObject baseFontObj)
{
return DirectObjectFinder.Find<CosName>(baseFontObj, pdfObjectParser, reader, isLenientParsing);
}
}
throw new InvalidFontFormatException($"Could not find a name for this font {dictionary}."); throw new InvalidFontFormatException($"Could not find a name for this font {dictionary}.");
} }
} }

View File

@@ -1,10 +1,9 @@
namespace UglyToad.PdfPig.Fonts.Parser.Handlers namespace UglyToad.PdfPig.Fonts.Parser.Handlers
{ {
using ContentStream; using Tokenization.Tokens;
using IO;
internal interface IFontHandler internal interface IFontHandler
{ {
IFont Generate(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing); IFont Generate(DictionaryToken dictionary, bool isLenientParsing);
} }
} }

View File

@@ -1,62 +1,62 @@
namespace UglyToad.PdfPig.Fonts.Parser.Handlers namespace UglyToad.PdfPig.Fonts.Parser.Handlers
{ {
using Cmap; using Cmap;
using ContentStream;
using Cos;
using Encodings; using Encodings;
using Exceptions; using Exceptions;
using Filters; using Filters;
using IO; using IO;
using Parts; using Parts;
using PdfPig.Parser; using PdfPig.Parser.Parts;
using Simple; using Simple;
using Tokenization.Scanner;
using Tokenization.Tokens;
using TrueType; using TrueType;
using TrueType.Parser; using TrueType.Parser;
internal class TrueTypeFontHandler : IFontHandler internal class TrueTypeFontHandler : IFontHandler
{ {
private readonly IPdfObjectParser pdfObjectParser;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly FontDescriptorFactory fontDescriptorFactory; private readonly FontDescriptorFactory fontDescriptorFactory;
private readonly TrueTypeFontParser trueTypeFontParser; private readonly TrueTypeFontParser trueTypeFontParser;
private readonly IEncodingReader encodingReader; private readonly IEncodingReader encodingReader;
private readonly IPdfObjectScanner pdfScanner;
public TrueTypeFontHandler(IPdfObjectParser pdfObjectParser, IFilterProvider filterProvider, public TrueTypeFontHandler(IPdfObjectScanner pdfScanner, IFilterProvider filterProvider,
CMapCache cMapCache, CMapCache cMapCache,
FontDescriptorFactory fontDescriptorFactory, FontDescriptorFactory fontDescriptorFactory,
TrueTypeFontParser trueTypeFontParser, TrueTypeFontParser trueTypeFontParser,
IEncodingReader encodingReader) IEncodingReader encodingReader)
{ {
this.pdfObjectParser = pdfObjectParser;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.fontDescriptorFactory = fontDescriptorFactory; this.fontDescriptorFactory = fontDescriptorFactory;
this.trueTypeFontParser = trueTypeFontParser; this.trueTypeFontParser = trueTypeFontParser;
this.encodingReader = encodingReader; this.encodingReader = encodingReader;
this.pdfScanner = pdfScanner;
} }
public IFont Generate(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
{ {
var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary); var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary);
var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary); var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary);
var widths = FontDictionaryAccessHelper.GetWidths(pdfObjectParser, dictionary, reader, isLenientParsing); var widths = FontDictionaryAccessHelper.GetWidths(pdfScanner, dictionary, isLenientParsing);
var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfObjectParser, fontDescriptorFactory, dictionary, reader, isLenientParsing); var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfScanner, fontDescriptorFactory, dictionary, isLenientParsing);
// TODO: use the parsed font fully. // TODO: use the parsed font fully.
//var font = ParseTrueTypeFont(descriptor, reader, isLenientParsing); //var font = ParseTrueTypeFont(descriptor, reader, isLenientParsing);
var name = FontDictionaryAccessHelper.GetName(pdfObjectParser, dictionary, descriptor, reader, isLenientParsing); var name = FontDictionaryAccessHelper.GetName(pdfScanner, dictionary, descriptor, isLenientParsing);
CMap toUnicodeCMap = null; CMap toUnicodeCMap = null;
if (dictionary.TryGetItemOfType(CosName.TO_UNICODE, out CosObject toUnicodeObj)) if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj))
{ {
var toUnicode = pdfObjectParser.Parse(toUnicodeObj.ToIndirectReference(), reader, isLenientParsing) as PdfRawStream; var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, pdfScanner);
var decodedUnicodeCMap = toUnicode?.Decode(filterProvider); var decodedUnicodeCMap = toUnicode.Decode(filterProvider);
if (decodedUnicodeCMap != null) if (decodedUnicodeCMap != null)
{ {
@@ -64,7 +64,7 @@
} }
} }
Encoding encoding = encodingReader.Read(dictionary, reader, isLenientParsing, descriptor); Encoding encoding = encodingReader.Read(dictionary, isLenientParsing, descriptor);
return new TrueTypeSimpleFont(name, firstCharacter, lastCharacter, widths, descriptor, toUnicodeCMap, encoding); return new TrueTypeSimpleFont(name, firstCharacter, lastCharacter, widths, descriptor, toUnicodeCMap, encoding);
} }
@@ -83,18 +83,18 @@
$"Expected a TrueType font in the TrueType font descriptor, instead it was {descriptor.FontFile.FileType}."); $"Expected a TrueType font in the TrueType font descriptor, instead it was {descriptor.FontFile.FileType}.");
} }
var fontFileStream = pdfObjectParser.Parse(descriptor.FontFile.ObjectKey, reader, isLenientParsing) as PdfRawStream; //var fontFileStream = pdfObjectParser.Parse(descriptor.FontFile.ObjectKey, reader, isLenientParsing) as PdfRawStream;
if (fontFileStream == null) //if (fontFileStream == null)
{ {
return null; return null;
} }
var fontFile = fontFileStream.Decode(filterProvider); //var fontFile = fontFileStream.Decode(filterProvider);
var font = trueTypeFontParser.Parse(new TrueTypeDataBytes(new ByteArrayInputBytes(fontFile))); //var font = trueTypeFontParser.Parse(new TrueTypeDataBytes(new ByteArrayInputBytes(fontFile)));
return font; //return font;
} }
} }
} }

View File

@@ -4,13 +4,10 @@
using CidFonts; using CidFonts;
using Cmap; using Cmap;
using Composite; using Composite;
using ContentStream;
using Cos;
using Exceptions; using Exceptions;
using Filters; using Filters;
using IO; using IO;
using Parts; using Parts;
using PdfPig.Parser;
using PdfPig.Parser.Parts; using PdfPig.Parser.Parts;
using Tokenization.Scanner; using Tokenization.Scanner;
using Tokenization.Tokens; using Tokenization.Tokens;
@@ -21,20 +18,18 @@
private readonly CidFontFactory cidFontFactory; private readonly CidFontFactory cidFontFactory;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IPdfObjectParser pdfObjectParser;
private readonly IPdfObjectScanner scanner; private readonly IPdfObjectScanner scanner;
public Type0FontHandler(CidFontFactory cidFontFactory, CMapCache cMapCache, IFilterProvider filterProvider, IPdfObjectParser pdfObjectParser, public Type0FontHandler(CidFontFactory cidFontFactory, CMapCache cMapCache, IFilterProvider filterProvider,
IPdfObjectScanner scanner) IPdfObjectScanner scanner)
{ {
this.cidFontFactory = cidFontFactory; this.cidFontFactory = cidFontFactory;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.pdfObjectParser = pdfObjectParser;
this.scanner = scanner; this.scanner = scanner;
} }
public IFont Generate(DictionaryToken dictionary, IRandomAccessRead reader, bool isLenientParsing) public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
{ {
var baseFont = dictionary.GetNameOrDefault(NameToken.BaseFont); var baseFont = dictionary.GetNameOrDefault(NameToken.BaseFont);
@@ -57,7 +52,7 @@
descendantFontDictionary = (DictionaryToken) descendantObject; descendantFontDictionary = (DictionaryToken) descendantObject;
} }
cidFont = ParseDescendant(descendantFontDictionary, reader, isLenientParsing); cidFont = ParseDescendant(descendantFontDictionary, isLenientParsing);
} }
else else
{ {
@@ -122,7 +117,7 @@
return false; return false;
} }
private ICidFont ParseDescendant(DictionaryToken dictionary, IRandomAccessRead reader, bool isLenientParsing) private ICidFont ParseDescendant(DictionaryToken dictionary, bool isLenientParsing)
{ {
var type = dictionary.GetNameOrDefault(NameToken.Type); var type = dictionary.GetNameOrDefault(NameToken.Type);
if (type?.Equals(NameToken.Font) != true) if (type?.Equals(NameToken.Font) != true)
@@ -130,7 +125,7 @@
throw new InvalidFontFormatException($"Expected \'Font\' dictionary but found \'{type}\'"); throw new InvalidFontFormatException($"Expected \'Font\' dictionary but found \'{type}\'");
} }
var result = cidFontFactory.Generate(dictionary, reader, isLenientParsing); var result = cidFontFactory.Generate(dictionary, isLenientParsing);
return result; return result;
} }

View File

@@ -2,13 +2,12 @@
{ {
using Cmap; using Cmap;
using ContentStream; using ContentStream;
using Cos;
using Encodings; using Encodings;
using Exceptions; using Exceptions;
using Filters; using Filters;
using IO; using IO;
using Parts; using Parts;
using PdfPig.Parser; using PdfPig.Parser.Parts;
using Simple; using Simple;
using Tokenization.Scanner; using Tokenization.Scanner;
using Tokenization.Tokens; using Tokenization.Tokens;
@@ -17,41 +16,40 @@
internal class Type1FontHandler : IFontHandler internal class Type1FontHandler : IFontHandler
{ {
private readonly IPdfObjectParser pdfObjectParser; private readonly IPdfObjectScanner pdfScanner;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly FontDescriptorFactory fontDescriptorFactory; private readonly FontDescriptorFactory fontDescriptorFactory;
private readonly IEncodingReader encodingReader; private readonly IEncodingReader encodingReader;
private readonly IPdfObjectScanner scanner;
private readonly Type1FontParser type1FontParser; private readonly Type1FontParser type1FontParser;
public Type1FontHandler(IPdfObjectParser pdfObjectParser, CMapCache cMapCache, IFilterProvider filterProvider, public Type1FontHandler(IPdfObjectScanner pdfScanner, CMapCache cMapCache, IFilterProvider filterProvider,
FontDescriptorFactory fontDescriptorFactory, IEncodingReader encodingReader, FontDescriptorFactory fontDescriptorFactory,
IPdfObjectScanner scanner, IEncodingReader encodingReader,
Type1FontParser type1FontParser) Type1FontParser type1FontParser)
{ {
this.pdfObjectParser = pdfObjectParser; this.pdfScanner = pdfScanner;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.fontDescriptorFactory = fontDescriptorFactory; this.fontDescriptorFactory = fontDescriptorFactory;
this.encodingReader = encodingReader; this.encodingReader = encodingReader;
this.scanner = scanner;
this.type1FontParser = type1FontParser; this.type1FontParser = type1FontParser;
} }
public IFont Generate(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
{ {
var usingStandard14Only = !dictionary.ContainsKey(CosName.FIRST_CHAR) || !dictionary.ContainsKey(CosName.WIDTHS); var usingStandard14Only = !dictionary.ContainsKey(NameToken.FirstChar) || !dictionary.ContainsKey(NameToken.Widths);
if (usingStandard14Only) if (usingStandard14Only)
{ {
// TODO: some fonts combine standard 14 font with other metrics. // TODO: some fonts combine standard 14 font with other metrics.
if (!dictionary.TryGetName(CosName.BASE_FONT, out var standard14Name)) if (!dictionary.TryGet(NameToken.BaseFont, out var baseFontToken)
|| !(baseFontToken is NameToken standard14Name))
{ {
throw new InvalidFontFormatException($"The Type 1 font did not contain a first character entry but also did not reference a standard 14 font: {dictionary}"); throw new InvalidFontFormatException($"The Type 1 font did not contain a first character entry but also did not reference a standard 14 font: {dictionary}");
} }
var metrics = Standard14.GetAdobeFontMetrics(standard14Name.Name); var metrics = Standard14.GetAdobeFontMetrics(standard14Name.Data);
return new Type1Standard14Font(metrics); return new Type1Standard14Font(metrics);
} }
@@ -60,18 +58,18 @@
var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary); var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary);
var widths = FontDictionaryAccessHelper.GetWidths(pdfObjectParser, dictionary, reader, isLenientParsing); var widths = FontDictionaryAccessHelper.GetWidths(pdfScanner, dictionary, isLenientParsing);
var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfObjectParser, fontDescriptorFactory, dictionary, reader, isLenientParsing); var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfScanner, fontDescriptorFactory, dictionary, isLenientParsing);
var font = ParseType1Font(descriptor, isLenientParsing); var font = ParseType1Font(descriptor, isLenientParsing);
var name = FontDictionaryAccessHelper.GetName(pdfObjectParser, dictionary, descriptor, reader, isLenientParsing); var name = FontDictionaryAccessHelper.GetName(pdfScanner, dictionary, descriptor, isLenientParsing);
CMap toUnicodeCMap = null; CMap toUnicodeCMap = null;
if (dictionary.TryGetItemOfType(CosName.TO_UNICODE, out CosObject toUnicodeObj)) if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj))
{ {
var toUnicode = pdfObjectParser.Parse(toUnicodeObj.ToIndirectReference(), reader, isLenientParsing) as PdfRawStream; var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, pdfScanner);
var decodedUnicodeCMap = toUnicode?.Decode(filterProvider); var decodedUnicodeCMap = toUnicode?.Decode(filterProvider);
@@ -81,7 +79,7 @@
} }
} }
Encoding encoding = encodingReader.Read(dictionary, reader, isLenientParsing, descriptor); Encoding encoding = encodingReader.Read(dictionary, isLenientParsing, descriptor);
if (encoding == null && font?.Encoding.Count > 0) if (encoding == null && font?.Encoding.Count > 0)
{ {
@@ -98,14 +96,14 @@
return null; return null;
} }
if (descriptor.FontFile.ObjectKey.ObjectNumber == 0) if (descriptor.FontFile.ObjectKey.Data.ObjectNumber == 0)
{ {
return null; return null;
} }
try try
{ {
var stream = scanner.Get(descriptor.FontFile.ObjectKey).Data as StreamToken; var stream = pdfScanner.Get(descriptor.FontFile.ObjectKey.Data).Data as StreamToken;
if (stream == null) if (stream == null)
{ {

View File

@@ -1,50 +1,50 @@
namespace UglyToad.PdfPig.Fonts.Parser.Handlers namespace UglyToad.PdfPig.Fonts.Parser.Handlers
{ {
using System;
using Cmap; using Cmap;
using ContentStream;
using Core; using Core;
using Cos;
using Encodings; using Encodings;
using Exceptions; using Exceptions;
using Filters; using Filters;
using Geometry; using Geometry;
using IO; using IO;
using PdfPig.Parser;
using PdfPig.Parser.Parts; using PdfPig.Parser.Parts;
using Simple; using Simple;
using Tokenization.Scanner;
using Tokenization.Tokens;
using Util;
internal class Type3FontHandler : IFontHandler internal class Type3FontHandler : IFontHandler
{ {
private readonly IPdfObjectParser pdfObjectParser;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IEncodingReader encodingReader; private readonly IEncodingReader encodingReader;
private readonly IPdfObjectScanner scanner;
public Type3FontHandler(IPdfObjectParser pdfObjectParser, CMapCache cMapCache, IFilterProvider filterProvider, IEncodingReader encodingReader) public Type3FontHandler(IPdfObjectScanner scanner, CMapCache cMapCache, IFilterProvider filterProvider,
IEncodingReader encodingReader)
{ {
this.pdfObjectParser = pdfObjectParser;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.encodingReader = encodingReader; this.encodingReader = encodingReader;
this.scanner = scanner;
} }
public IFont Generate(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
{ {
var boundingBox = GetBoundingBox(dictionary); var boundingBox = GetBoundingBox(dictionary);
var fontMatrix = GetFontMatrix(dictionary, reader, isLenientParsing); var fontMatrix = GetFontMatrix(dictionary);
var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary); var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary);
var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary); var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary);
var widths = FontDictionaryAccessHelper.GetWidths(pdfObjectParser, dictionary, reader, isLenientParsing); var widths = FontDictionaryAccessHelper.GetWidths(scanner, dictionary, isLenientParsing);
Encoding encoding = encodingReader.Read(dictionary, reader, isLenientParsing); Encoding encoding = encodingReader.Read(dictionary, isLenientParsing);
CMap toUnicodeCMap = null; CMap toUnicodeCMap = null;
if (dictionary.TryGetItemOfType(CosName.TO_UNICODE, out CosObject toUnicodeObj)) if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj))
{ {
var toUnicode = pdfObjectParser.Parse(toUnicodeObj.ToIndirectReference(), reader, isLenientParsing) as PdfRawStream; var toUnicode = DirectObjectFinder.Get<StreamToken>(toUnicodeObj, scanner);
var decodedUnicodeCMap = toUnicode?.Decode(filterProvider); var decodedUnicodeCMap = toUnicode?.Decode(filterProvider);
@@ -54,86 +54,35 @@
} }
} }
return new Type3Font(CosName.TYPE3, boundingBox, fontMatrix, encoding, firstCharacter, return new Type3Font(NameToken.Type3, boundingBox, fontMatrix, encoding, firstCharacter,
lastCharacter, widths, toUnicodeCMap); lastCharacter, widths, toUnicodeCMap);
} }
private TransformationMatrix GetFontMatrix(PdfDictionary dictionary, IRandomAccessRead reader, bool isLenientParsing) private TransformationMatrix GetFontMatrix(DictionaryToken dictionary)
{ {
if (!dictionary.TryGetValue(CosName.FONT_MATRIX, out var matrixObject)) if (!dictionary.TryGet(NameToken.FontMatrix, out var matrixObject))
{ {
throw new InvalidFontFormatException($"No font matrix found: {dictionary}."); throw new InvalidFontFormatException($"No font matrix found: {dictionary}.");
} }
COSArray matrixArray; var matrixArray = DirectObjectFinder.Get<ArrayToken>(matrixObject, scanner);
if (matrixObject is COSArray arr)
{ return TransformationMatrix.FromValues(matrixArray.GetNumeric(0).Data, matrixArray.GetNumeric(1).Data,
matrixArray = arr; matrixArray.GetNumeric(2).Data, matrixArray.GetNumeric(3).Data, matrixArray.GetNumeric(4).Data,
} matrixArray.GetNumeric(5).Data);
else if (matrixObject is CosObject obj)
{
matrixArray = DirectObjectFinder.Find<COSArray>(obj, pdfObjectParser, reader, isLenientParsing);
}
else
{
throw new InvalidFontFormatException($"The font matrix object was not an array or reference to an array: {matrixObject}.");
}
return TransformationMatrix.FromValues(GetDecimal(matrixArray, 0), GetDecimal(matrixArray, 1),
GetDecimal(matrixArray, 2), GetDecimal(matrixArray, 3), GetDecimal(matrixArray, 4), GetDecimal(matrixArray, 5));
} }
private Encoding GetEncoding(CosBase baseObject, IRandomAccessRead reader, bool isLenientParsing) private static PdfRectangle GetBoundingBox(DictionaryToken dictionary)
{ {
if (baseObject is CosObject obj) if (!dictionary.TryGet(NameToken.FontBbox, out var bboxObject))
{
baseObject = pdfObjectParser.Parse(obj.ToIndirectReference(), reader, isLenientParsing);
}
if (baseObject is CosName encodingName)
{
}
else if (baseObject is PdfDictionary dictionary)
{
}
else
{
throw new InvalidFontFormatException("");
}
throw new NotImplementedException();
}
private static decimal GetDecimal(COSArray array, int index)
{
if (index >= array.Count)
{
throw new InvalidFontFormatException($"The array did not contain enough entries to be the font matrix: {array}.");
}
var item = array.get(index) as ICosNumber;
if (item == null)
{
throw new InvalidFontFormatException($"The array did not contain a decimal at position {index}: {array}.");
}
return item.AsDecimal();
}
private static PdfRectangle GetBoundingBox(PdfDictionary dictionary)
{
if (!dictionary.TryGetValue(CosName.FONT_BBOX, out var bboxObject))
{ {
throw new InvalidFontFormatException($"Type 3 font was invalid. No Font Bounding Box: {dictionary}."); throw new InvalidFontFormatException($"Type 3 font was invalid. No Font Bounding Box: {dictionary}.");
} }
if (bboxObject is COSArray bboxArray) if (bboxObject is ArrayToken bboxArray)
{ {
return new PdfRectangle(GetDecimal(bboxArray, 0), GetDecimal(bboxArray, 1), return new PdfRectangle(bboxArray.GetNumeric(0).Data, bboxArray.GetNumeric(1).Data,
GetDecimal(bboxArray, 2), GetDecimal(bboxArray, 3)); bboxArray.GetNumeric(2).Data, bboxArray.GetNumeric(3).Data);
} }
return new PdfRectangle(0, 0, 0, 0); return new PdfRectangle(0, 0, 0, 0);

View File

@@ -1,11 +1,10 @@
namespace UglyToad.PdfPig.Fonts.Parser namespace UglyToad.PdfPig.Fonts.Parser
{ {
using ContentStream;
using Encodings; using Encodings;
using IO; using Tokenization.Tokens;
internal interface IEncodingReader internal interface IEncodingReader
{ {
Encoding Read(PdfDictionary fontDictionary, IRandomAccessRead reader, bool isLenientParsing, FontDescriptor descriptor = null); Encoding Read(DictionaryToken fontDictionary, bool isLenientParsing, FontDescriptor descriptor = null);
} }
} }

View File

@@ -3,12 +3,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using CidFonts; using CidFonts;
using ContentStream;
using Exceptions; using Exceptions;
using Filters; using Filters;
using Geometry; using Geometry;
using IO; using IO;
using PdfPig.Parser;
using PdfPig.Parser.Parts; using PdfPig.Parser.Parts;
using Tokenization.Scanner; using Tokenization.Scanner;
using Tokenization.Tokens; using Tokenization.Tokens;
@@ -20,23 +18,19 @@
{ {
private readonly FontDescriptorFactory descriptorFactory; private readonly FontDescriptorFactory descriptorFactory;
private readonly TrueTypeFontParser trueTypeFontParser; private readonly TrueTypeFontParser trueTypeFontParser;
private readonly IPdfObjectParser pdfObjectParser;
private readonly IFilterProvider filterProvider; private readonly IFilterProvider filterProvider;
private readonly IPdfObjectScanner pdfScanner; private readonly IPdfObjectScanner pdfScanner;
public CidFontFactory(FontDescriptorFactory descriptorFactory, TrueTypeFontParser trueTypeFontParser, public CidFontFactory(IPdfObjectScanner pdfScanner, FontDescriptorFactory descriptorFactory, TrueTypeFontParser trueTypeFontParser,
IPdfObjectParser pdfObjectParser, IFilterProvider filterProvider)
IFilterProvider filterProvider,
IPdfObjectScanner pdfScanner)
{ {
this.descriptorFactory = descriptorFactory; this.descriptorFactory = descriptorFactory;
this.trueTypeFontParser = trueTypeFontParser; this.trueTypeFontParser = trueTypeFontParser;
this.pdfObjectParser = pdfObjectParser;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
this.pdfScanner = pdfScanner; this.pdfScanner = pdfScanner;
} }
public ICidFont Generate(DictionaryToken dictionary, IRandomAccessRead reader, bool isLenientParsing) public ICidFont Generate(DictionaryToken dictionary, bool isLenientParsing)
{ {
var type = dictionary.GetNameOrDefault(NameToken.Type); var type = dictionary.GetNameOrDefault(NameToken.Type);
if (!NameToken.Font.Equals(type)) if (!NameToken.Font.Equals(type))
@@ -53,11 +47,11 @@
descriptor = descriptorFactory.Generate(descriptorDictionary, isLenientParsing); descriptor = descriptorFactory.Generate(descriptorDictionary, isLenientParsing);
} }
var fontProgram = ReadDescriptorFile(descriptor, reader, isLenientParsing); var fontProgram = ReadDescriptorFile(descriptor);
var baseFont = dictionary.GetNameOrDefault(NameToken.BaseFont); var baseFont = dictionary.GetNameOrDefault(NameToken.BaseFont);
var systemInfo = GetSystemInfo(dictionary, reader, isLenientParsing); var systemInfo = GetSystemInfo(dictionary);
var subType = dictionary.GetNameOrDefault(NameToken.Subtype); var subType = dictionary.GetNameOrDefault(NameToken.Subtype);
if (NameToken.CidFontType0.Equals(subType)) if (NameToken.CidFontType0.Equals(subType))
@@ -89,14 +83,14 @@
return true; return true;
} }
private ICidFontProgram ReadDescriptorFile(FontDescriptor descriptor, IRandomAccessRead reader, bool isLenientParsing) private ICidFontProgram ReadDescriptorFile(FontDescriptor descriptor)
{ {
if (descriptor?.FontFile == null) if (descriptor?.FontFile == null)
{ {
return null; return null;
} }
var fontFileStream = pdfObjectParser.Parse(descriptor.FontFile.ObjectKey, reader, isLenientParsing) as PdfRawStream; var fontFileStream = DirectObjectFinder.Get<StreamToken>(descriptor.FontFile.ObjectKey, pdfScanner);
if (fontFileStream == null) if (fontFileStream == null)
{ {
@@ -219,7 +213,7 @@
return new VerticalWritingMetrics(dw2, verticalDisplacements, positionVectors); return new VerticalWritingMetrics(dw2, verticalDisplacements, positionVectors);
} }
private CharacterIdentifierSystemInfo GetSystemInfo(DictionaryToken dictionary, IRandomAccessRead reader, bool isLenientParsing) private CharacterIdentifierSystemInfo GetSystemInfo(DictionaryToken dictionary)
{ {
if(!dictionary.TryGet(NameToken.CidSystemInfo, out var cidEntry)) if(!dictionary.TryGet(NameToken.CidSystemInfo, out var cidEntry))
{ {
@@ -236,14 +230,14 @@
DirectObjectFinder.Get<DictionaryToken>(cidEntry, pdfScanner); DirectObjectFinder.Get<DictionaryToken>(cidEntry, pdfScanner);
} }
var registry = SafeKeyAccess(cidDictionary, NameToken.Registry, reader, isLenientParsing); var registry = SafeKeyAccess(cidDictionary, NameToken.Registry);
var ordering = SafeKeyAccess(cidDictionary, NameToken.Ordering, reader, isLenientParsing); var ordering = SafeKeyAccess(cidDictionary, NameToken.Ordering);
var supplement = cidDictionary.GetIntOrDefault(NameToken.Supplement); var supplement = cidDictionary.GetIntOrDefault(NameToken.Supplement);
return new CharacterIdentifierSystemInfo(registry, ordering, supplement); return new CharacterIdentifierSystemInfo(registry, ordering, supplement);
} }
private string SafeKeyAccess(DictionaryToken dictionary, NameToken keyName, IRandomAccessRead reader, bool isLenientParsing) private string SafeKeyAccess(DictionaryToken dictionary, NameToken keyName)
{ {
if (!dictionary.TryGet(keyName, out var token)) if (!dictionary.TryGet(keyName, out var token))
{ {

View File

@@ -1,15 +1,14 @@
namespace UglyToad.PdfPig.Fonts.Parser.Parts namespace UglyToad.PdfPig.Fonts.Parser.Parts
{ {
using System; using System;
using ContentStream;
using ContentStream.TypedAccessors;
using Cos;
using Geometry; using Geometry;
using Tokenization.Tokens;
using Util;
using Util.JetBrains.Annotations; using Util.JetBrains.Annotations;
internal class FontDescriptorFactory internal class FontDescriptorFactory
{ {
public FontDescriptor Generate(PdfDictionary dictionary, bool isLenientParsing) public FontDescriptor Generate(DictionaryToken dictionary, bool isLenientParsing)
{ {
if (dictionary == null) if (dictionary == null)
{ {
@@ -28,31 +27,41 @@
{ {
FontFamily = family, FontFamily = family,
Stretch = stretch, Stretch = stretch,
FontWeight = dictionary.GetDecimalOrDefault(CosName.FONT_WEIGHT, 0), FontWeight = GetDecimalOrDefault(dictionary, NameToken.FontWeight),
BoundingBox = bounding, BoundingBox = bounding,
ItalicAngle = dictionary.GetDecimalOrDefault(CosName.ITALIC_ANGLE, 0), ItalicAngle = GetDecimalOrDefault(dictionary, NameToken.ItalicAngle),
Ascent = dictionary.GetDecimalOrDefault(CosName.ASCENT, 0), Ascent = GetDecimalOrDefault(dictionary, NameToken.Ascent),
Descent = dictionary.GetDecimalOrDefault(CosName.DESCENT, 0), Descent = GetDecimalOrDefault(dictionary, NameToken.Descent),
Leading = dictionary.GetDecimalOrDefault(CosName.LEADING, 0), Leading = GetDecimalOrDefault(dictionary, NameToken.Leading),
CapHeight = Math.Abs(dictionary.GetDecimalOrDefault(CosName.CAP_HEIGHT, 0)), CapHeight = Math.Abs(GetDecimalOrDefault(dictionary, NameToken.CapHeight)),
XHeight = Math.Abs(dictionary.GetDecimalOrDefault(CosName.XHEIGHT, 0)), XHeight = Math.Abs(GetDecimalOrDefault(dictionary, NameToken.Xheight)),
StemVertical = dictionary.GetDecimalOrDefault(CosName.STEM_V, 0), StemVertical = GetDecimalOrDefault(dictionary, NameToken.StemV),
StemHorizontal = dictionary.GetDecimalOrDefault(CosName.STEM_H, 0), StemHorizontal = GetDecimalOrDefault(dictionary, NameToken.StemH),
AverageWidth = dictionary.GetDecimalOrDefault(CosName.AVG_WIDTH, 0), AverageWidth = GetDecimalOrDefault(dictionary, NameToken.AvgWidth),
MaxWidth = dictionary.GetDecimalOrDefault(CosName.MAX_WIDTH, 0), MaxWidth = GetDecimalOrDefault(dictionary, NameToken.MaxWidth),
MissingWidth = dictionary.GetDecimalOrDefault(CosName.MISSING_WIDTH, 0), MissingWidth = GetDecimalOrDefault(dictionary, NameToken.MissingWidth),
FontFile = fontFile, FontFile = fontFile,
CharSet = charSet CharSet = charSet
}; };
} }
private static CosName GetFontName(PdfDictionary dictionary, bool isLenientParsing) private static decimal GetDecimalOrDefault(DictionaryToken dictionary, NameToken name)
{ {
if (!dictionary.TryGetName(CosName.FONT_NAME, out var name)) if (!dictionary.TryGet(name, out var token) || !(token is NumericToken number))
{
return 0;
}
return number.Data;
}
private static NameToken GetFontName(DictionaryToken dictionary, bool isLenientParsing)
{
if (!dictionary.TryGet(NameToken.FontName, out var name) || !(name is NameToken nameToken))
{ {
if (isLenientParsing) if (isLenientParsing)
{ {
name = CosName.Create(string.Empty); nameToken = NameToken.Create(string.Empty);
} }
else else
{ {
@@ -60,32 +69,32 @@
} }
} }
return name; return nameToken;
} }
private static string GetFontFamily(PdfDictionary dictionary) private static string GetFontFamily(DictionaryToken dictionary)
{ {
if (dictionary.TryGetItemOfType<CosString>(CosName.FONT_FAMILY, out var value)) if (dictionary.TryGet(NameToken.FontFamily, out var value) && value is StringToken fontFamily)
{ {
return value.GetString(); return fontFamily.Data;
} }
return string.Empty; return string.Empty;
} }
private static FontStretch GetFontStretch(PdfDictionary dictionary) private static FontStretch GetFontStretch(DictionaryToken dictionary)
{ {
if (!dictionary.TryGetName(CosName.FONT_STRETCH, out var stretch)) if (!dictionary.TryGet(NameToken.FontStretch, out var stretch) || !(stretch is NameToken stretchName))
{ {
return FontStretch.Normal; return FontStretch.Normal;
} }
return stretch.ConvertToFontStretch(); return stretchName.ConvertToFontStretch();
} }
private static FontFlags GetFlags(PdfDictionary dictionary, bool isLenientParsing) private static FontFlags GetFlags(DictionaryToken dictionary, bool isLenientParsing)
{ {
var flags = dictionary.GetIntOrDefault(CosName.FLAGS, -1); var flags = dictionary.GetIntOrDefault(NameToken.Flags, -1);
if (flags == -1) if (flags == -1)
{ {
@@ -102,66 +111,66 @@
return (FontFlags) flags; return (FontFlags) flags;
} }
private static PdfRectangle GetBoundingBox(PdfDictionary dictionary) private static PdfRectangle GetBoundingBox(DictionaryToken dictionary)
{ {
if (!dictionary.TryGetItemOfType<COSArray>(CosName.FONT_BBOX, out var box)) if (!dictionary.TryGet(NameToken.FontBbox, out var box) || !(box is ArrayToken boxArray))
{ {
return new PdfRectangle(0, 0, 0, 0); return new PdfRectangle(0, 0, 0, 0);
} }
if (box.Count != 4) if (boxArray.Data.Count != 4)
{ {
return new PdfRectangle(0, 0, 0, 0); return new PdfRectangle(0, 0, 0, 0);
} }
var x1 = box.getInt(0); var x1 = boxArray.GetNumeric(0).Data;
var y1 = box.getInt(1); var y1 = boxArray.GetNumeric(1).Data;
var x2 = box.getInt(2); var x2 = boxArray.GetNumeric(2).Data;
var y2 = box.getInt(3); var y2 = boxArray.GetNumeric(3).Data;
return new PdfRectangle(x1, y1, x2, y2); return new PdfRectangle(x1, y1, x2, y2);
} }
private static string GetCharSet(PdfDictionary dictionary) private static string GetCharSet(DictionaryToken dictionary)
{ {
if (!dictionary.TryGetName(CosName.CHAR_SET, out var set)) if (!dictionary.TryGet(NameToken.CharSet, out var set) || !(set is NameToken setName))
{ {
return null; return null;
} }
return set.Name; return setName.Data;
} }
[CanBeNull] [CanBeNull]
private static DescriptorFontFile GetFontFile(PdfDictionary dictionary) private static DescriptorFontFile GetFontFile(DictionaryToken dictionary)
{ {
if (dictionary.TryGetValue(CosName.FONT_FILE, out var value)) if (dictionary.TryGet(NameToken.FontFile, out var value))
{ {
if (!(value is CosObject obj)) if (!(value is IndirectReferenceToken obj))
{ {
throw new NotSupportedException("We currently expect the FontFile to be an object reference."); throw new NotSupportedException("We currently expect the FontFile to be an object reference.");
} }
return new DescriptorFontFile(obj.ToIndirectReference(), DescriptorFontFile.FontFileType.Type1); return new DescriptorFontFile(obj, DescriptorFontFile.FontFileType.Type1);
} }
if (dictionary.TryGetValue(CosName.FONT_FILE2, out value)) if (dictionary.TryGet(NameToken.FontFile2, out value))
{ {
if (!(value is CosObject obj)) if (!(value is IndirectReferenceToken obj))
{ {
throw new NotSupportedException("We currently expect the FontFile2 to be an object reference."); throw new NotSupportedException("We currently expect the FontFile2 to be an object reference.");
} }
return new DescriptorFontFile(obj.ToIndirectReference(), DescriptorFontFile.FontFileType.TrueType); return new DescriptorFontFile(obj, DescriptorFontFile.FontFileType.TrueType);
} }
if (dictionary.TryGetValue(CosName.FONT_FILE3, out value)) if (dictionary.TryGet(NameToken.FontFile3, out value))
{ {
if (!(value is CosObject obj)) if (!(value is IndirectReferenceToken obj))
{ {
throw new NotSupportedException("We currently expect the FontFile3 to be an object reference."); throw new NotSupportedException("We currently expect the FontFile3 to be an object reference.");
} }
return new DescriptorFontFile(obj.ToIndirectReference(), DescriptorFontFile.FontFileType.FromSubtype); return new DescriptorFontFile(obj, DescriptorFontFile.FontFileType.FromSubtype);
} }
return null; return null;

View File

@@ -130,7 +130,7 @@
var width = displacement.X * fontSize * TextMatrices.TextMatrix.GetScalingFactorX() * transformationMatrix.A; var width = displacement.X * fontSize * TextMatrices.TextMatrix.GetScalingFactorX() * transformationMatrix.A;
ShowGlyph(renderingMatrix, font, code, unicode, width, fontSize, pointSize); ShowGlyph(renderingMatrix, font, unicode, width, fontSize, pointSize);
decimal tx, ty; decimal tx, ty;
if (font.IsVertical) if (font.IsVertical)
@@ -208,12 +208,12 @@
TextMatrices.TextMatrix = newMatrix; TextMatrices.TextMatrix = newMatrix;
} }
private void ShowGlyph(TransformationMatrix renderingMatrix, IFont font, int characterCode, string unicode, decimal width, decimal fontSize, private void ShowGlyph(TransformationMatrix renderingMatrix, IFont font, string unicode, decimal width, decimal fontSize,
decimal pointSize) decimal pointSize)
{ {
var location = new PdfPoint(renderingMatrix.E, renderingMatrix.F); var location = new PdfPoint(renderingMatrix.E, renderingMatrix.F);
var letter = new Letter(unicode, location, width, fontSize, font.Name.Name, pointSize); var letter = new Letter(unicode, location, width, fontSize, font.Name.Data, pointSize);
Letters.Add(letter); Letters.Add(letter);
} }

View File

@@ -22,8 +22,8 @@
private readonly IPageContentParser pageContentParser; private readonly IPageContentParser pageContentParser;
private readonly IPdfObjectScanner pdfScanner; private readonly IPdfObjectScanner pdfScanner;
public PageFactory(IResourceStore resourceStore, IFilterProvider filterProvider, public PageFactory(IPdfObjectScanner pdfScanner, IResourceStore resourceStore, IFilterProvider filterProvider,
IPageContentParser pageContentParser, IPdfObjectScanner pdfScanner) IPageContentParser pageContentParser)
{ {
this.resourceStore = resourceStore; this.resourceStore = resourceStore;
this.filterProvider = filterProvider; this.filterProvider = filterProvider;
@@ -132,10 +132,10 @@
CropBox cropBox; CropBox cropBox;
if (dictionary.TryGet(NameToken.CropBox, out var cropBoxObject) && cropBoxObject is ArrayToken cropBoxArray) if (dictionary.TryGet(NameToken.CropBox, out var cropBoxObject) && cropBoxObject is ArrayToken cropBoxArray)
{ {
var x1 = cropBoxArray.GetNumeric(0).Data; var x1 = cropBoxArray.GetNumeric(0).Int;
var y1 = cropBoxArray.GetNumeric(1).Data; var y1 = cropBoxArray.GetNumeric(1).Int;
var x2 = cropBoxArray.GetNumeric(2).Data; var x2 = cropBoxArray.GetNumeric(2).Int;
var y2 = cropBoxArray.GetNumeric(3).Data; var y2 = cropBoxArray.GetNumeric(3).Int;
cropBox = new CropBox(new PdfRectangle(x1, y1, x2, y2)); cropBox = new CropBox(new PdfRectangle(x1, y1, x2, y2));
} }
@@ -152,10 +152,10 @@
MediaBox mediaBox; MediaBox mediaBox;
if (dictionary.TryGet(NameToken.MediaBox, out var mediaboxObject) && mediaboxObject is ArrayToken mediaboxArray) if (dictionary.TryGet(NameToken.MediaBox, out var mediaboxObject) && mediaboxObject is ArrayToken mediaboxArray)
{ {
var x1 = mediaboxArray.GetNumeric(0).Data; var x1 = mediaboxArray.GetNumeric(0).Int;
var y1 = mediaboxArray.GetNumeric(1).Data; var y1 = mediaboxArray.GetNumeric(1).Int;
var x2 = mediaboxArray.GetNumeric(2).Data; var x2 = mediaboxArray.GetNumeric(2).Int;
var y2 = mediaboxArray.GetNumeric(3).Data; var y2 = mediaboxArray.GetNumeric(3).Int;
mediaBox = new MediaBox(new PdfRectangle(x1, y1, x2, y2)); mediaBox = new MediaBox(new PdfRectangle(x1, y1, x2, y2));
} }

View File

@@ -79,24 +79,23 @@
var trueTypeFontParser = new TrueTypeFontParser(); var trueTypeFontParser = new TrueTypeFontParser();
var fontDescriptorFactory = new FontDescriptorFactory(); var fontDescriptorFactory = new FontDescriptorFactory();
var cidFontFactory = new CidFontFactory(fontDescriptorFactory, trueTypeFontParser, pdfObjectParser, filterProvider); var pdfScanner = new PdfTokenScanner(inputBytes, new ObjectLocationProvider(crossReferenceTable, pool, bruteForceSearcher));
var encodingReader = new EncodingReader(pdfObjectParser); var cidFontFactory = new CidFontFactory(pdfScanner, fontDescriptorFactory, trueTypeFontParser, filterProvider);
var encodingReader = new EncodingReader(pdfScanner);
var cMapCache = new CMapCache(new CMapParser()); var cMapCache = new CMapCache(new CMapParser());
var pdfScanner = new PdfTokenScanner(inputBytes, new ObjectLocationProvider(crossReferenceTable, pool, bruteForceSearcher));
var fontFactory = new FontFactory(log, new Type0FontHandler(cidFontFactory, var fontFactory = new FontFactory(log, new Type0FontHandler(cidFontFactory,
cMapCache, cMapCache,
filterProvider, filterProvider, pdfScanner),
pdfObjectParser), new TrueTypeFontHandler(pdfScanner, filterProvider, cMapCache, fontDescriptorFactory, trueTypeFontParser, encodingReader),
new TrueTypeFontHandler(pdfObjectParser, filterProvider, cMapCache, fontDescriptorFactory, trueTypeFontParser, encodingReader), new Type1FontHandler(pdfScanner, cMapCache, filterProvider, fontDescriptorFactory, encodingReader, new Type1FontParser()),
new Type1FontHandler(pdfObjectParser, cMapCache, filterProvider, fontDescriptorFactory, encodingReader, pdfScanner, new Type1FontParser()), new Type3FontHandler(pdfScanner, cMapCache, filterProvider, encodingReader));
new Type3FontHandler(pdfObjectParser, cMapCache, filterProvider, encodingReader));
var dynamicParser = container.Get<DynamicParser>(); var dynamicParser = container.Get<DynamicParser>();
var resourceContainer = new ResourceContainer(pdfObjectParser, fontFactory); var resourceContainer = new ResourceContainer(pdfScanner, fontFactory);
var pageFactory = new PageFactory(resourceContainer, pdfObjectParser, filterProvider, new PageContentParser(new ReflectionGraphicsStateOperationFactory())); var pageFactory = new PageFactory(pdfScanner, resourceContainer, filterProvider, new PageContentParser(new ReflectionGraphicsStateOperationFactory()));
var informationFactory = new DocumentInformationFactory(); var informationFactory = new DocumentInformationFactory();
var catalogFactory = new CatalogFactory(pdfScanner); var catalogFactory = new CatalogFactory(pdfScanner);
@@ -110,7 +109,7 @@
var caching = new ParsingCachingProviders(pool, bruteForceSearcher, resourceContainer); var caching = new ParsingCachingProviders(pool, bruteForceSearcher, resourceContainer);
return new PdfDocument(log, reader, version, crossReferenceTable, isLenientParsing, caching, pageFactory, pdfObjectParser, catalog, information, return new PdfDocument(log, reader, version, crossReferenceTable, isLenientParsing, caching, pageFactory, catalog, information,
pdfScanner); pdfScanner);
} }

View File

@@ -55,7 +55,6 @@
bool isLenientParsing, bool isLenientParsing,
ParsingCachingProviders cachingProviders, ParsingCachingProviders cachingProviders,
IPageFactory pageFactory, IPageFactory pageFactory,
IPdfObjectParser pdfObjectParser,
Catalog catalog, Catalog catalog,
DocumentInformation information, IPdfObjectScanner pdfScanner) DocumentInformation information, IPdfObjectScanner pdfScanner)
{ {
@@ -68,7 +67,7 @@
this.pdfScanner = pdfScanner; this.pdfScanner = pdfScanner;
Information = information ?? throw new ArgumentNullException(nameof(information)); Information = information ?? throw new ArgumentNullException(nameof(information));
Catalog = catalog ?? throw new ArgumentNullException(nameof(catalog)); Catalog = catalog ?? throw new ArgumentNullException(nameof(catalog));
Pages = new Pages(log, Catalog, pdfObjectParser, pageFactory, reader, isLenientParsing, pdfScanner); Pages = new Pages(log, Catalog, pageFactory, reader, isLenientParsing, pdfScanner);
} }
/// <summary> /// <summary>

View File

@@ -35,7 +35,19 @@
public bool TryGetOffset(IndirectReference reference, out long offset) public bool TryGetOffset(IndirectReference reference, out long offset)
{ {
return offsets.TryGetValue(reference, out offset); if (offsets.TryGetValue(reference, out offset))
{
return true;
}
var locations = searcher.GetObjectLocations();
if (locations.TryGetValue(reference, out offset))
{
return true;
}
return false;
} }
public void UpdateOffset(IndirectReference reference, long offset) public void UpdateOffset(IndirectReference reference, long offset)

View File

@@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ContentStream;
internal class ArrayToken : IDataToken<IReadOnlyList<IToken>> internal class ArrayToken : IDataToken<IReadOnlyList<IToken>>
{ {
@@ -10,7 +11,35 @@
public ArrayToken(IReadOnlyList<IToken> data) public ArrayToken(IReadOnlyList<IToken> data)
{ {
Data = data ?? throw new ArgumentNullException(nameof(data)); if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var previousPrevious = default(IToken);
var previous = default(IToken);
var result = new List<IToken>();
foreach (var token in data)
{
// Roll any "number number R" sequence into an indirect reference
if (ReferenceEquals(token, OperatorToken.R) && previous is NumericToken generation && previousPrevious is NumericToken objectNumber)
{
// Clear the previous 2 tokens.
result.RemoveRange(result.Count - 2, 2);
result.Add(new IndirectReferenceToken(new IndirectReference(objectNumber.Long, generation.Int)));
}
else
{
result.Add(token);
}
previousPrevious = previous;
previous = token;
}
Data = result;
} }
public override string ToString() public override string ToString()

View File

@@ -1,7 +1,11 @@
namespace UglyToad.PdfPig.Tokenization.Tokens namespace UglyToad.PdfPig.Tokenization.Tokens
{ {
using System.Collections.Concurrent;
internal partial class NameToken internal partial class NameToken
{ {
private static readonly ConcurrentDictionary<string, NameToken> NameMap = new ConcurrentDictionary<string, NameToken>();
#region A #region A
public static readonly NameToken A = new NameToken("A"); public static readonly NameToken A = new NameToken("A");
public static readonly NameToken Aa = new NameToken("AA"); public static readonly NameToken Aa = new NameToken("AA");

View File

@@ -1,13 +1,9 @@
namespace UglyToad.PdfPig.Tokenization.Tokens namespace UglyToad.PdfPig.Tokenization.Tokens
{ {
using System.Collections.Concurrent;
internal partial class NameToken : IDataToken<string> internal partial class NameToken : IDataToken<string>
{ {
private static readonly ConcurrentDictionary<string, NameToken> NameMap = new ConcurrentDictionary<string, NameToken>();
public string Data { get; } public string Data { get; }
private NameToken(string text) private NameToken(string text)
{ {
NameMap[text] = this; NameMap[text] = this;
@@ -47,7 +43,7 @@
public override string ToString() public override string ToString()
{ {
return Data; return $"/{Data}";
} }
} }
} }