diff --git a/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs b/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs index b6e17e47e..79d64c23c 100644 --- a/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs +++ b/src/UglyToad.PdfPig/Writer/PdfPageBuilder.cs @@ -831,7 +831,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) // We need to relocate the resources, and we have to make sure that none of the resources collide with // the already written operation's resources - var resources = pageDictionary.GetOrCreateDict(NameToken.Resources); + var resources = pageDictionary.GetOrCreateDict(NameToken.Resources, srcPage.pdfScanner); foreach (var set in srcResourceDictionary.Data) { @@ -858,7 +858,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) // Since we don't directly add font's to the pages resources, we have to go look at the document's font if (srcResourceDictionary.TryGet(NameToken.Font, srcPage.pdfScanner, out DictionaryToken? fontsDictionary)) { - var pageFontsDictionary = resources.GetOrCreateDict(NameToken.Font); + var pageFontsDictionary = resources.GetOrCreateDict(NameToken.Font, srcPage.pdfScanner); foreach (var fontSet in fontsDictionary.Data) { @@ -903,7 +903,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) // Since we don't directly add xobjects's to the pages resources, we have to go look at the document's xobjects if (srcResourceDictionary.TryGet(NameToken.Xobject, srcPage.pdfScanner, out DictionaryToken? xobjectsDictionary)) { - var pageXobjectsDictionary = resources.GetOrCreateDict(NameToken.Xobject); + var pageXobjectsDictionary = resources.GetOrCreateDict(NameToken.Xobject, srcPage.pdfScanner); foreach (var xobjectSet in xobjectsDictionary.Data) { @@ -945,7 +945,7 @@ public PdfPageBuilder CopyFrom(Page srcPage) // Since we don't directly add xobjects's to the pages resources, we have to go look at the document's xobjects if (srcResourceDictionary.TryGet(NameToken.ExtGState, srcPage.pdfScanner, out DictionaryToken? gsDictionary)) { - var pageGstateDictionary = resources.GetOrCreateDict(NameToken.ExtGState); + var pageGstateDictionary = resources.GetOrCreateDict(NameToken.ExtGState, srcPage.pdfScanner); foreach (var gstate in gsDictionary.Data) { diff --git a/src/UglyToad.PdfPig/Writer/WriterUtil.cs b/src/UglyToad.PdfPig/Writer/WriterUtil.cs index 52cbe4b4d..d2798ff76 100644 --- a/src/UglyToad.PdfPig/Writer/WriterUtil.cs +++ b/src/UglyToad.PdfPig/Writer/WriterUtil.cs @@ -12,38 +12,36 @@ internal static class WriterUtil { - public static Dictionary GetOrCreateDict(this Dictionary dict, NameToken key) + public static Dictionary GetOrCreateDict( + this Dictionary dict, + T key, + IPdfTokenScanner? sourceScanner = null) where T : notnull { if (dict.TryGetValue(key, out var item)) { - if (!(item is DictionaryToken dt)) + var chainCount = 0; + var itemChain = item; + while (itemChain is IndirectReferenceToken ir && chainCount < 100) { - throw new ApplicationException("Expected dictionary token, got " + item.GetType()); - } + if (sourceScanner == null) + { + break; + } - if (dt.Data is Dictionary mutable) - { - return mutable; - } + itemChain = sourceScanner.Get(ir.Data); - mutable = dt.Data. - ToDictionary(x => x.Key, x => x.Value); - dict[key] = DictionaryToken.With(mutable); - return mutable; - } + chainCount++; - var created = new Dictionary(); - dict[key] = DictionaryToken.With(created); - return created; - } + if (itemChain is ObjectToken ot) + { + itemChain = ot.Data; + } + } - public static Dictionary GetOrCreateDict(this Dictionary dict, string key) - { - if (dict.TryGetValue(key, out var item)) - { - if (!(item is DictionaryToken dt)) + if (itemChain is not DictionaryToken dt) { - throw new ApplicationException("Expected dictionary token, got " + item.GetType()); + throw new InvalidOperationException( + $"While trying to copy token called {key} which should have been a dictionary token we found a token of type {item.GetType()}"); } if (dt.Data is Dictionary mutable) @@ -61,6 +59,7 @@ public static Dictionary GetOrCreateDict(this Dictionary /// The purpose of this method is to resolve indirect reference. That mean copy the reference's content to the new document's stream /// and replace the indirect reference with the correct/new one