mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-08-20 09:21:57 +08:00
account for skipmissingfonts in positioned text #637
This commit is contained in:
parent
6daa2ec192
commit
9d2b3f914d
@ -1,106 +1,106 @@
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using Core;
|
||||
using Outline;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Util;
|
||||
|
||||
internal class Pages
|
||||
{
|
||||
private readonly IPageFactory pageFactory;
|
||||
private readonly IPdfTokenScanner pdfScanner;
|
||||
private readonly Dictionary<int, PageTreeNode> pagesByNumber;
|
||||
namespace UglyToad.PdfPig.Content
|
||||
{
|
||||
using Core;
|
||||
using Outline;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Tokenization.Scanner;
|
||||
using Tokens;
|
||||
using Util;
|
||||
|
||||
internal class Pages
|
||||
{
|
||||
private readonly IPageFactory pageFactory;
|
||||
private readonly IPdfTokenScanner pdfScanner;
|
||||
private readonly Dictionary<int, PageTreeNode> pagesByNumber;
|
||||
public int Count => pagesByNumber.Count;
|
||||
|
||||
/// <summary>
|
||||
/// The page tree for this document containing all pages, page numbers and their dictionaries.
|
||||
/// </summary>
|
||||
public PageTreeNode PageTree { get; }
|
||||
|
||||
internal Pages(IPageFactory pageFactory, IPdfTokenScanner pdfScanner, PageTreeNode pageTree, Dictionary<int, PageTreeNode> pagesByNumber)
|
||||
{
|
||||
this.pageFactory = pageFactory ?? throw new ArgumentNullException(nameof(pageFactory));
|
||||
this.pdfScanner = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner));
|
||||
this.pagesByNumber = pagesByNumber;
|
||||
PageTree = pageTree;
|
||||
}
|
||||
|
||||
internal Page GetPage(int pageNumber, NamedDestinations namedDestinations, InternalParsingOptions parsingOptions)
|
||||
{
|
||||
if (pageNumber <= 0 || pageNumber > Count)
|
||||
{
|
||||
parsingOptions.Logger.Error($"Page {pageNumber} requested but is out of range.");
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(pageNumber),
|
||||
$"Page number {pageNumber} invalid, must be between 1 and {Count}.");
|
||||
}
|
||||
|
||||
var pageNode = GetPageNode(pageNumber);
|
||||
var pageStack = new Stack<PageTreeNode>();
|
||||
|
||||
var currentNode = pageNode;
|
||||
while (currentNode != null)
|
||||
{
|
||||
pageStack.Push(currentNode);
|
||||
currentNode = currentNode.Parent;
|
||||
}
|
||||
|
||||
var pageTreeMembers = new PageTreeMembers();
|
||||
|
||||
while (pageStack.Count > 0)
|
||||
{
|
||||
currentNode = pageStack.Pop();
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resourcesDictionary))
|
||||
{
|
||||
pageTreeMembers.ParentResources.Enqueue(resourcesDictionary);
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken mediaBox))
|
||||
{
|
||||
pageTreeMembers.MediaBox = new MediaBox(mediaBox.ToRectangle(pdfScanner));
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Rotate, pdfScanner, out NumericToken rotateToken))
|
||||
{
|
||||
pageTreeMembers.Rotation = rotateToken.Int;
|
||||
}
|
||||
/// </summary>
|
||||
public PageTreeNode PageTree { get; }
|
||||
|
||||
internal Pages(IPageFactory pageFactory, IPdfTokenScanner pdfScanner, PageTreeNode pageTree, Dictionary<int, PageTreeNode> pagesByNumber)
|
||||
{
|
||||
this.pageFactory = pageFactory ?? throw new ArgumentNullException(nameof(pageFactory));
|
||||
this.pdfScanner = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner));
|
||||
this.pagesByNumber = pagesByNumber;
|
||||
PageTree = pageTree;
|
||||
}
|
||||
|
||||
internal Page GetPage(int pageNumber, NamedDestinations namedDestinations, InternalParsingOptions parsingOptions)
|
||||
{
|
||||
if (pageNumber <= 0 || pageNumber > Count)
|
||||
{
|
||||
parsingOptions.Logger.Error($"Page {pageNumber} requested but is out of range.");
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(pageNumber),
|
||||
$"Page number {pageNumber} invalid, must be between 1 and {Count}.");
|
||||
}
|
||||
|
||||
var page = pageFactory.Create(
|
||||
pageNumber,
|
||||
pageNode.NodeDictionary,
|
||||
pageTreeMembers,
|
||||
namedDestinations,
|
||||
parsingOptions);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
internal PageTreeNode GetPageNode(int pageNumber)
|
||||
{
|
||||
if (!pagesByNumber.TryGetValue(pageNumber, out var node))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find page node by number for: {pageNumber}.");
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
internal PageTreeNode GetPageByReference(IndirectReference reference)
|
||||
{
|
||||
foreach (var page in pagesByNumber)
|
||||
{
|
||||
if (page.Value.Reference.Equals(reference))
|
||||
{
|
||||
return page.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pageNode = GetPageNode(pageNumber);
|
||||
var pageStack = new Stack<PageTreeNode>();
|
||||
|
||||
var currentNode = pageNode;
|
||||
while (currentNode != null)
|
||||
{
|
||||
pageStack.Push(currentNode);
|
||||
currentNode = currentNode.Parent;
|
||||
}
|
||||
|
||||
var pageTreeMembers = new PageTreeMembers();
|
||||
|
||||
while (pageStack.Count > 0)
|
||||
{
|
||||
currentNode = pageStack.Pop();
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Resources, pdfScanner, out DictionaryToken resourcesDictionary))
|
||||
{
|
||||
pageTreeMembers.ParentResources.Enqueue(resourcesDictionary);
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.MediaBox, pdfScanner, out ArrayToken mediaBox))
|
||||
{
|
||||
pageTreeMembers.MediaBox = new MediaBox(mediaBox.ToRectangle(pdfScanner));
|
||||
}
|
||||
|
||||
if (currentNode.NodeDictionary.TryGet(NameToken.Rotate, pdfScanner, out NumericToken rotateToken))
|
||||
{
|
||||
pageTreeMembers.Rotation = rotateToken.Int;
|
||||
}
|
||||
}
|
||||
|
||||
var page = pageFactory.Create(
|
||||
pageNumber,
|
||||
pageNode.NodeDictionary,
|
||||
pageTreeMembers,
|
||||
namedDestinations,
|
||||
parsingOptions);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
internal PageTreeNode GetPageNode(int pageNumber)
|
||||
{
|
||||
if (!pagesByNumber.TryGetValue(pageNumber, out var node))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find page node by number for: {pageNumber}.");
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
internal PageTreeNode GetPageByReference(IndirectReference reference)
|
||||
{
|
||||
foreach (var page in pagesByNumber)
|
||||
{
|
||||
if (page.Value.Reference.Equals(reference))
|
||||
{
|
||||
return page.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,6 +380,20 @@
|
||||
var horizontalScaling = textState.HorizontalScaling / 100.0;
|
||||
var font = resourceStore.GetFont(textState.FontName);
|
||||
|
||||
if (font == null)
|
||||
{
|
||||
if (parsingOptions.SkipMissingFonts)
|
||||
{
|
||||
parsingOptions.Logger.Warn($"Skipping a missing font with name {currentState.FontState.FontName} " +
|
||||
$"since it is not present in the document and {nameof(InternalParsingOptions.SkipMissingFonts)} " +
|
||||
"is set to true. This may result in some text being skipped and not included in the output.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Could not find the font with name {currentState.FontState.FontName} in the resource store. It has not been loaded yet.");
|
||||
}
|
||||
|
||||
var isVertical = font.IsVertical;
|
||||
|
||||
foreach (var token in tokens)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user