mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-19 19:07:56 +08:00
Merge branch 'master' of https://github.com/UglyToad/PdfPig
This commit is contained in:
@@ -6,7 +6,5 @@
|
||||
{
|
||||
Page Create(int number, DictionaryToken dictionary, PageTreeMembers pageTreeMembers,
|
||||
bool isLenientParsing);
|
||||
|
||||
void LoadResources(DictionaryToken dictionary, bool isLenientParsing);
|
||||
}
|
||||
}
|
@@ -7,6 +7,12 @@
|
||||
{
|
||||
void LoadResourceDictionary(DictionaryToken resourceDictionary, bool isLenientParsing);
|
||||
|
||||
/// <summary>
|
||||
/// Remove any named resources and associated state for the last resource dictionary loaded.
|
||||
/// Does not affect the cached resources, just the labels associated with them.
|
||||
/// </summary>
|
||||
void UnloadResourceDictionary();
|
||||
|
||||
IFont GetFont(NameToken name);
|
||||
|
||||
StreamToken GetXObject(NameToken name);
|
||||
|
@@ -1,5 +1,8 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Tokens;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the values inherited from the Page Tree for this page.
|
||||
/// </summary>
|
||||
@@ -13,5 +16,7 @@
|
||||
public MediaBox MediaBox { get; set; }
|
||||
|
||||
public int Rotation { get; set; }
|
||||
|
||||
public Queue<DictionaryToken> ParentResources { get; } = new Queue<DictionaryToken>();
|
||||
}
|
||||
}
|
@@ -45,12 +45,15 @@
|
||||
}
|
||||
|
||||
var pageTreeMembers = new PageTreeMembers();
|
||||
|
||||
|
||||
while (pageStack.Count > 0)
|
||||
{
|
||||
currentNode = pageStack.Pop();
|
||||
|
||||
pageFactory.LoadResources(currentNode.NodeDictionary, isLenientParsing);
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resourcesDictionary))
|
||||
{
|
||||
pageTreeMembers.ParentResources.Enqueue(resourcesDictionary);
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken mediaBox))
|
||||
{
|
||||
|
@@ -7,6 +7,7 @@
|
||||
using Parser.Parts;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Util;
|
||||
|
||||
internal class ResourceStore : IResourceStore
|
||||
{
|
||||
@@ -14,7 +15,7 @@
|
||||
private readonly IFontFactory fontFactory;
|
||||
|
||||
private readonly Dictionary<IndirectReference, IFont> loadedFonts = new Dictionary<IndirectReference, IFont>();
|
||||
private readonly Dictionary<NameToken, IndirectReference> currentResourceState = new Dictionary<NameToken, IndirectReference>();
|
||||
private readonly StackDictionary<NameToken, IndirectReference> currentResourceState = new StackDictionary<NameToken, IndirectReference>();
|
||||
|
||||
private readonly Dictionary<NameToken, DictionaryToken> extendedGraphicsStates = new Dictionary<NameToken, DictionaryToken>();
|
||||
|
||||
@@ -28,6 +29,8 @@
|
||||
|
||||
public void LoadResourceDictionary(DictionaryToken resourceDictionary, bool isLenientParsing)
|
||||
{
|
||||
currentResourceState.Push();
|
||||
|
||||
if (resourceDictionary.TryGet(NameToken.Font, out var fontBase))
|
||||
{
|
||||
var fontDictionary = DirectObjectFinder.Get<DictionaryToken>(fontBase, scanner);
|
||||
@@ -95,6 +98,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
public void UnloadResourceDictionary()
|
||||
{
|
||||
currentResourceState.Pop();
|
||||
}
|
||||
|
||||
private void LoadFontDictionary(DictionaryToken fontDictionary, bool isLenientParsing)
|
||||
{
|
||||
foreach (var pair in fontDictionary.Data)
|
||||
|
@@ -392,7 +392,9 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keyValuePair.Value is StringToken || keyValuePair.Value is ArrayToken || keyValuePair.Value is DictionaryToken)
|
||||
if (keyValuePair.Value is StringToken || keyValuePair.Value is ArrayToken
|
||||
|| keyValuePair.Value is DictionaryToken
|
||||
|| keyValuePair.Value is HexToken)
|
||||
{
|
||||
var inner = DecryptInternal(reference, keyValuePair.Value);
|
||||
dictionary = dictionary.With(keyValuePair.Key, inner);
|
||||
|
@@ -336,7 +336,8 @@
|
||||
* 5. Restore the saved graphics state, as if by invoking the Q operator.
|
||||
*/
|
||||
|
||||
if (formStream.StreamDictionary.TryGet<DictionaryToken>(NameToken.Resources, pdfScanner, out var formResources))
|
||||
var hasResources = formStream.StreamDictionary.TryGet<DictionaryToken>(NameToken.Resources, pdfScanner, out var formResources);
|
||||
if (hasResources)
|
||||
{
|
||||
resourceStore.LoadResourceDictionary(formResources, isLenientParsing);
|
||||
}
|
||||
@@ -368,6 +369,11 @@
|
||||
|
||||
// 5. Restore saved state.
|
||||
PopState();
|
||||
|
||||
if (hasResources)
|
||||
{
|
||||
resourceStore.UnloadResourceDictionary();
|
||||
}
|
||||
}
|
||||
|
||||
public void BeginSubpath()
|
||||
|
@@ -57,11 +57,25 @@
|
||||
|
||||
MediaBox mediaBox = GetMediaBox(number, dictionary, pageTreeMembers, isLenientParsing);
|
||||
CropBox cropBox = GetCropBox(dictionary, pageTreeMembers, mediaBox, isLenientParsing);
|
||||
|
||||
var stackDepth = 0;
|
||||
|
||||
while (pageTreeMembers.ParentResources.Count > 0)
|
||||
{
|
||||
var resource = pageTreeMembers.ParentResources.Dequeue();
|
||||
|
||||
resourceStore.LoadResourceDictionary(resource, isLenientParsing);
|
||||
stackDepth++;
|
||||
}
|
||||
|
||||
if (dictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resources))
|
||||
{
|
||||
resourceStore.LoadResourceDictionary(resources, isLenientParsing);
|
||||
stackDepth++;
|
||||
}
|
||||
|
||||
UserSpaceUnit userSpaceUnit = GetUserSpaceUnits(dictionary);
|
||||
|
||||
LoadResources(dictionary, isLenientParsing);
|
||||
|
||||
PageContent content = default(PageContent);
|
||||
|
||||
if (!dictionary.TryGet(NameToken.Contents, out var contents))
|
||||
@@ -114,6 +128,11 @@
|
||||
|
||||
var page = new Page(number, dictionary, mediaBox, cropBox, rotation, content, new AnnotationProvider(pdfScanner, dictionary, isLenientParsing));
|
||||
|
||||
for (var i = 0; i < stackDepth; i++)
|
||||
{
|
||||
resourceStore.UnloadResourceDictionary();
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -201,17 +220,5 @@
|
||||
|
||||
return mediaBox;
|
||||
}
|
||||
|
||||
public void LoadResources(DictionaryToken dictionary, bool isLenientParsing)
|
||||
{
|
||||
if (!dictionary.TryGet(NameToken.Resources, out var token))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var resources = DirectObjectFinder.Get<DictionaryToken>(token, pdfScanner);
|
||||
|
||||
resourceStore.LoadResourceDictionary(resources, isLenientParsing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
src/UglyToad.PdfPig/Util/StackDictionary.cs
Normal file
68
src/UglyToad.PdfPig/Util/StackDictionary.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
namespace UglyToad.PdfPig.Util
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class StackDictionary<K, V>
|
||||
{
|
||||
private readonly List<Dictionary<K, V>> values = new List<Dictionary<K, V>>();
|
||||
|
||||
public V this[K key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (TryGetValue(key, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
throw new KeyNotFoundException($"No item with key {key} in stack.");
|
||||
}
|
||||
set
|
||||
{
|
||||
if (values.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot set item in empty stack, call {nameof(Push)} before use.");
|
||||
}
|
||||
|
||||
values[values.Count - 1][key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(K key, out V result)
|
||||
{
|
||||
if (values.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot get item from empty stack, call {nameof(Push)} before use.");
|
||||
}
|
||||
|
||||
for (var i = values.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (values[i].TryGetValue(key, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
result = default(V);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Push()
|
||||
{
|
||||
values.Add(new Dictionary<K, V>());
|
||||
}
|
||||
|
||||
public void Pop()
|
||||
{
|
||||
if (values.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot pop empty stacked dictionary.");
|
||||
}
|
||||
|
||||
values.RemoveAt(values.Count - 1);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user