Skip to content

Commit 9d2b3f9

Browse files
committed
account for skipmissingfonts in positioned text #637
1 parent 6daa2ec commit 9d2b3f9

File tree

2 files changed

+115
-101
lines changed

2 files changed

+115
-101
lines changed

src/UglyToad.PdfPig/Content/Pages.cs

Lines changed: 101 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,106 @@
1-
namespace UglyToad.PdfPig.Content
2-
{
3-
using Core;
4-
using Outline;
5-
using System;
6-
using System.Collections.Generic;
7-
using Tokenization.Scanner;
8-
using Tokens;
9-
using Util;
10-
11-
internal class Pages
12-
{
13-
private readonly IPageFactory pageFactory;
14-
private readonly IPdfTokenScanner pdfScanner;
15-
private readonly Dictionary<int, PageTreeNode> pagesByNumber;
1+
namespace UglyToad.PdfPig.Content
2+
{
3+
using Core;
4+
using Outline;
5+
using System;
6+
using System.Collections.Generic;
7+
using Tokenization.Scanner;
8+
using Tokens;
9+
using Util;
10+
11+
internal class Pages
12+
{
13+
private readonly IPageFactory pageFactory;
14+
private readonly IPdfTokenScanner pdfScanner;
15+
private readonly Dictionary<int, PageTreeNode> pagesByNumber;
1616
public int Count => pagesByNumber.Count;
1717

1818
/// <summary>
1919
/// The page tree for this document containing all pages, page numbers and their dictionaries.
20-
/// </summary>
21-
public PageTreeNode PageTree { get; }
22-
23-
internal Pages(IPageFactory pageFactory, IPdfTokenScanner pdfScanner, PageTreeNode pageTree, Dictionary<int, PageTreeNode> pagesByNumber)
24-
{
25-
this.pageFactory = pageFactory ?? throw new ArgumentNullException(nameof(pageFactory));
26-
this.pdfScanner = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner));
27-
this.pagesByNumber = pagesByNumber;
28-
PageTree = pageTree;
29-
}
30-
31-
internal Page GetPage(int pageNumber, NamedDestinations namedDestinations, InternalParsingOptions parsingOptions)
32-
{
33-
if (pageNumber <= 0 || pageNumber > Count)
34-
{
35-
parsingOptions.Logger.Error($"Page {pageNumber} requested but is out of range.");
36-
37-
throw new ArgumentOutOfRangeException(nameof(pageNumber),
38-
$"Page number {pageNumber} invalid, must be between 1 and {Count}.");
39-
}
40-
41-
var pageNode = GetPageNode(pageNumber);
42-
var pageStack = new Stack<PageTreeNode>();
43-
44-
var currentNode = pageNode;
45-
while (currentNode != null)
46-
{
47-
pageStack.Push(currentNode);
48-
currentNode = currentNode.Parent;
49-
}
50-
51-
var pageTreeMembers = new PageTreeMembers();
52-
53-
while (pageStack.Count > 0)
54-
{
55-
currentNode = pageStack.Pop();
56-
57-
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resourcesDictionary))
58-
{
59-
pageTreeMembers.ParentResources.Enqueue(resourcesDictionary);
60-
}
61-
62-
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken mediaBox))
63-
{
64-
pageTreeMembers.MediaBox = new MediaBox(mediaBox.ToRectangle(pdfScanner));
65-
}
66-
67-
if (currentNode.NodeDictionary.TryGet(NameToken.Rotate, pdfScanner, out NumericToken rotateToken))
68-
{
69-
pageTreeMembers.Rotation = rotateToken.Int;
70-
}
20+
/// </summary>
21+
public PageTreeNode PageTree { get; }
22+
23+
internal Pages(IPageFactory pageFactory, IPdfTokenScanner pdfScanner, PageTreeNode pageTree, Dictionary<int, PageTreeNode> pagesByNumber)
24+
{
25+
this.pageFactory = pageFactory ?? throw new ArgumentNullException(nameof(pageFactory));
26+
this.pdfScanner = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner));
27+
this.pagesByNumber = pagesByNumber;
28+
PageTree = pageTree;
29+
}
30+
31+
internal Page GetPage(int pageNumber, NamedDestinations namedDestinations, InternalParsingOptions parsingOptions)
32+
{
33+
if (pageNumber <= 0 || pageNumber > Count)
34+
{
35+
parsingOptions.Logger.Error($"Page {pageNumber} requested but is out of range.");
36+
37+
throw new ArgumentOutOfRangeException(nameof(pageNumber),
38+
$"Page number {pageNumber} invalid, must be between 1 and {Count}.");
39+
}
40+
41+
var pageNode = GetPageNode(pageNumber);
42+
var pageStack = new Stack<PageTreeNode>();
43+
44+
var currentNode = pageNode;
45+
while (currentNode != null)
46+
{
47+
pageStack.Push(currentNode);
48+
currentNode = currentNode.Parent;
49+
}
50+
51+
var pageTreeMembers = new PageTreeMembers();
52+
53+
while (pageStack.Count > 0)
54+
{
55+
currentNode = pageStack.Pop();
56+
57+
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resourcesDictionary))
58+
{
59+
pageTreeMembers.ParentResources.Enqueue(resourcesDictionary);
60+
}
61+
62+
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken mediaBox))
63+
{
64+
pageTreeMembers.MediaBox = new MediaBox(mediaBox.ToRectangle(pdfScanner));
65+
}
66+
67+
if (currentNode.NodeDictionary.TryGet(NameToken.Rotate, pdfScanner, out NumericToken rotateToken))
68+
{
69+
pageTreeMembers.Rotation = rotateToken.Int;
70+
}
71+
}
72+
73+
var page = pageFactory.Create(
74+
pageNumber,
75+
pageNode.NodeDictionary,
76+
pageTreeMembers,
77+
namedDestinations,
78+
parsingOptions);
79+
80+
return page;
81+
}
82+
83+
internal PageTreeNode GetPageNode(int pageNumber)
84+
{
85+
if (!pagesByNumber.TryGetValue(pageNumber, out var node))
86+
{
87+
throw new InvalidOperationException($"Could not find page node by number for: {pageNumber}.");
7188
}
72-
73-
var page = pageFactory.Create(
74-
pageNumber,
75-
pageNode.NodeDictionary,
76-
pageTreeMembers,
77-
namedDestinations,
78-
parsingOptions);
79-
80-
return page;
81-
}
82-
83-
internal PageTreeNode GetPageNode(int pageNumber)
84-
{
85-
if (!pagesByNumber.TryGetValue(pageNumber, out var node))
86-
{
87-
throw new InvalidOperationException($"Could not find page node by number for: {pageNumber}.");
88-
}
89-
90-
return node;
91-
}
92-
93-
internal PageTreeNode GetPageByReference(IndirectReference reference)
94-
{
95-
foreach (var page in pagesByNumber)
96-
{
97-
if (page.Value.Reference.Equals(reference))
98-
{
99-
return page.Value;
100-
}
101-
}
102-
103-
return null;
104-
}
105-
}
106-
}
89+
90+
return node;
91+
}
92+
93+
internal PageTreeNode GetPageByReference(IndirectReference reference)
94+
{
95+
foreach (var page in pagesByNumber)
96+
{
97+
if (page.Value.Reference.Equals(reference))
98+
{
99+
return page.Value;
100+
}
101+
}
102+
103+
return null;
104+
}
105+
}
106+
}

src/UglyToad.PdfPig/Graphics/ContentStreamProcessor.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,20 @@ public void ShowPositionedText(IReadOnlyList<IToken> tokens)
380380
var horizontalScaling = textState.HorizontalScaling / 100.0;
381381
var font = resourceStore.GetFont(textState.FontName);
382382

383+
if (font == null)
384+
{
385+
if (parsingOptions.SkipMissingFonts)
386+
{
387+
parsingOptions.Logger.Warn($"Skipping a missing font with name {currentState.FontState.FontName} " +
388+
$"since it is not present in the document and {nameof(InternalParsingOptions.SkipMissingFonts)} " +
389+
"is set to true. This may result in some text being skipped and not included in the output.");
390+
391+
return;
392+
}
393+
394+
throw new InvalidOperationException($"Could not find the font with name {currentState.FontState.FontName} in the resource store. It has not been loaded yet.");
395+
}
396+
383397
var isVertical = font.IsVertical;
384398

385399
foreach (var token in tokens)

0 commit comments

Comments
 (0)