changes for intital InusualZ review

This commit is contained in:
Plaisted 2021-02-10 20:18:03 -06:00
parent 509164447b
commit ef0bcd2055
5 changed files with 68 additions and 125 deletions

View File

@ -1,33 +1,19 @@
namespace UglyToad.PdfPig.Writer
{
using Core;
using Graphics.Operations;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using Tokens;
internal class PdfDedupStreamWriter : IPdfStreamWriter
internal class PdfDedupStreamWriter : PdfStreamWriter
{
public Stream Stream { get; }
private int CurrentNumber { get; set; } = 1;
private bool DisposeStream { get; set; }
private const decimal DefaultVersion = 1.2m;
private bool Initialized { get; set; }
private readonly Dictionary<IndirectReference, long> offsets = new Dictionary<IndirectReference, long>();
private readonly Dictionary<byte[], IndirectReferenceToken> hashes = new Dictionary<byte[], IndirectReferenceToken>(new FNVByteComparison());
public PdfDedupStreamWriter(Stream stream, bool dispose)
public PdfDedupStreamWriter(Stream stream, bool dispose) : base(stream, dispose)
{
Stream = stream;
DisposeStream = dispose;
}
private MemoryStream ms = new MemoryStream();
public IndirectReferenceToken WriteToken(IToken token)
private readonly MemoryStream ms = new MemoryStream();
public override IndirectReferenceToken WriteToken(IToken token)
{
if (!Initialized)
{
@ -51,7 +37,7 @@ using Core;
return ir;
}
public IndirectReferenceToken WriteToken(IToken token, IndirectReferenceToken indirectReference)
public override IndirectReferenceToken WriteToken(IToken token, IndirectReferenceToken indirectReference)
{
if (!Initialized)
{
@ -68,45 +54,10 @@ using Core;
return indirectReference;
}
public IndirectReferenceToken ReserveObjectNumber()
public new void Dispose()
{
return new IndirectReferenceToken(new IndirectReference(CurrentNumber++, 0));
}
public void InitializePdf(decimal version)
{
WriteString($"%PDF-{version.ToString("0.0", CultureInfo.InvariantCulture)}", Stream);
Stream.WriteText("%");
Stream.WriteByte(169);
Stream.WriteByte(205);
Stream.WriteByte(196);
Stream.WriteByte(210);
Stream.WriteNewLine();
Initialized = true;
}
public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference=null)
{
TokenWriter.WriteCrossReferenceTable(offsets, catalogReference.Data, Stream, documentInformationReference?.Data);
}
private static void WriteString(string text, Stream stream)
{
var bytes = OtherEncodings.StringAsLatin1Bytes(text);
stream.Write(bytes, 0, bytes.Length);
stream.WriteNewLine();
}
public void Dispose()
{
if (DisposeStream)
{
Stream.Dispose();
}
hashes.Clear();
base.Dispose();
}
class FNVByteComparison : IEqualityComparer<byte[]>

View File

@ -27,7 +27,7 @@ namespace UglyToad.PdfPig.Writer
private readonly Dictionary<int, PdfPageBuilder> pages = new Dictionary<int, PdfPageBuilder>();
private readonly Dictionary<Guid, FontStored> fonts = new Dictionary<Guid, FontStored>();
private bool completed = false;
internal int fontId = 0;
internal int fontId = 0;
private readonly static ArrayToken DefaultProcSet = new ArrayToken(new List<NameToken>
{
@ -284,7 +284,7 @@ namespace UglyToad.PdfPig.Writer
internal class PageInfo
{
public DictionaryToken Page { get; set; }
public List<DictionaryToken> Parents { get; set; }
public IReadOnlyList<DictionaryToken> Parents { get; set; }
}
private readonly ConditionalWeakTable<IPdfTokenScanner, Dictionary<IndirectReference, IndirectReferenceToken>> existingCopies =
new ConditionalWeakTable<IPdfTokenScanner, Dictionary<IndirectReference, IndirectReferenceToken>>();
@ -320,18 +320,15 @@ namespace UglyToad.PdfPig.Writer
existingTrees.Add(document, pagesInfos);
}
if (!pagesInfos.ContainsKey(pageNumber))
if (!pagesInfos.TryGetValue(pageNumber, out PageInfo pageInfo))
{
throw new KeyNotFoundException($"Page {pageNumber} was not found in the source document.");
}
var pageInfo = pagesInfos[pageNumber];
// copy content streams
var streams = new List<PdfPageBuilder.CopiedContentStream>();
if (pageInfo.Page.ContainsKey(NameToken.Contents))
if (pageInfo.Page.TryGet(NameToken.Contents, out IToken token))
{
var token = pageInfo.Page.Data[NameToken.Contents];
if (token is ArrayToken array)
{
foreach (var item in array.Data)
@ -358,9 +355,9 @@ namespace UglyToad.PdfPig.Writer
// just put all parent resources into new page
foreach (var dict in pageInfo.Parents)
{
if (dict.TryGet(NameToken.Resources, out var token))
if (dict.TryGet(NameToken.Resources, out var resourceToken))
{
CopyResourceDict(token, resources);
CopyResourceDict(resourceToken, resources);
}
}
@ -382,6 +379,8 @@ namespace UglyToad.PdfPig.Writer
WriterUtil.CopyToken(context, kvp.Value, document.Structure.TokenScanner, refs);
}
// LocalizeFontAndXObject(resources); TODO work in progress
copiedPageDict[NameToken.Resources] = new DictionaryToken(resources);
var builder = new PdfPageBuilder(pages.Count + 1, this, streams, copiedPageDict);
@ -444,7 +443,7 @@ namespace UglyToad.PdfPig.Writer
return dict;
}
}
private void CompleteDocument()
{
// write fonts to reserved object numbers
@ -453,7 +452,7 @@ namespace UglyToad.PdfPig.Writer
font.Value.FontProgram.WriteFont(context, font.Value.FontKey.Reference);
}
int desiredLeafSize = 25;
const int desiredLeafSize = 25; // allow customization at some point?
var numLeafs = (int) Math.Ceiling(Decimal.Divide(Pages.Count, desiredLeafSize));
var leafRefs = new List<IndirectReferenceToken>();

View File

@ -747,15 +747,6 @@
return value;
}
internal interface IPageContentStream : IContentStream
{
bool ReadOnly { get; }
bool HasContent { get; }
void Add(IGraphicsStateOperation operation);
IndirectReferenceToken Write(IPdfStreamWriter writer);
}
/// <summary>
/// Provides access to the raw page data structures for advanced editing use cases.
/// </summary>
@ -767,6 +758,15 @@
List<IGraphicsStateOperation> Operations { get; }
}
internal interface IPageContentStream : IContentStream
{
bool ReadOnly { get; }
bool HasContent { get; }
void Add(IGraphicsStateOperation operation);
IndirectReferenceToken Write(IPdfStreamWriter writer);
}
internal class DefaultContentStream : IPageContentStream
{
private readonly List<IGraphicsStateOperation> operations;

View File

@ -13,16 +13,13 @@
/// </summary>
internal class PdfStreamWriter : IPdfStreamWriter
{
private Dictionary<IndirectReference, long> offsets = new Dictionary<IndirectReference, long>();
private const decimal DefaultVersion = 1.2m;
private bool Initialized { get; set; }
private int CurrentNumber { get; set; } = 1;
protected const decimal DefaultVersion = 1.2m;
protected Dictionary<IndirectReference, long> offsets = new Dictionary<IndirectReference, long>();
protected bool DisposeStream { get; set; }
protected bool Initialized { get; set; }
protected int CurrentNumber { get; set; } = 1;
public Stream Stream { get; set; }
private bool DisposeStream { get; set; }
public PdfStreamWriter(Stream baseStream, bool disposeStream = true)
internal PdfStreamWriter(Stream baseStream, bool disposeStream = true)
{
Stream = baseStream ?? throw new ArgumentNullException(nameof(baseStream));
if (!baseStream.CanWrite)
@ -33,40 +30,9 @@
DisposeStream = disposeStream;
}
public void InitializePdf(decimal version)
{
WriteString($"%PDF-{version.ToString("0.0", CultureInfo.InvariantCulture)}", Stream);
public Stream Stream { get; protected set; }
Stream.WriteText("%");
Stream.WriteByte(169);
Stream.WriteByte(205);
Stream.WriteByte(196);
Stream.WriteByte(210);
Stream.WriteNewLine();
Initialized = true;
}
public void Dispose()
{
if (!DisposeStream)
{
Stream = null;
return;
}
Stream?.Dispose();
Stream = null;
}
private static void WriteString(string text, Stream stream)
{
var bytes = OtherEncodings.StringAsLatin1Bytes(text);
stream.Write(bytes, 0, bytes.Length);
stream.WriteNewLine();
}
public IndirectReferenceToken WriteToken(IToken token)
public virtual IndirectReferenceToken WriteToken(IToken token)
{
if (!Initialized)
{
@ -80,7 +46,7 @@
return ir;
}
public IndirectReferenceToken WriteToken(IToken token, IndirectReferenceToken indirectReference)
public virtual IndirectReferenceToken WriteToken(IToken token, IndirectReferenceToken indirectReference)
{
if (!Initialized)
{
@ -98,10 +64,39 @@
return new IndirectReferenceToken(new IndirectReference(CurrentNumber++, 0));
}
public void InitializePdf(decimal version)
{
WriteString($"%PDF-{version.ToString("0.0", CultureInfo.InvariantCulture)}", Stream);
public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference=null)
Stream.WriteText("%");
Stream.WriteByte(169);
Stream.WriteByte(205);
Stream.WriteByte(196);
Stream.WriteByte(210);
Stream.WriteNewLine();
Initialized = true;
}
public void CompletePdf(IndirectReferenceToken catalogReference, IndirectReferenceToken documentInformationReference = null)
{
TokenWriter.WriteCrossReferenceTable(offsets, catalogReference.Data, Stream, documentInformationReference?.Data);
}
private static void WriteString(string text, Stream stream)
{
var bytes = OtherEncodings.StringAsLatin1Bytes(text);
stream.Write(bytes, 0, bytes.Length);
stream.WriteNewLine();
}
public void Dispose()
{
if (DisposeStream)
{
Stream?.Dispose();
}
Stream = null;
}
}
}

View File

@ -14,9 +14,8 @@
{
public static Dictionary<string, IToken> GetOrCreateDict(this Dictionary<NameToken, IToken> dict, NameToken key)
{
if (dict.ContainsKey(key))
if (dict.TryGetValue(key, out var item))
{
var item = dict[key];
if (!(item is DictionaryToken dt))
{
throw new ApplicationException("Expected dictionary token, got " + item.GetType());
@ -40,9 +39,8 @@
public static Dictionary<string, IToken> GetOrCreateDict(this Dictionary<string, IToken> dict, string key)
{
if (dict.ContainsKey(key))
if (dict.TryGetValue(key, out var item))
{
var item = dict[key];
if (!(item is DictionaryToken dt))
{
throw new ApplicationException("Expected dictionary token, got " + item.GetType());
@ -161,7 +159,7 @@
return tokenToCopy;
}
internal static IEnumerable<(DictionaryToken, List<DictionaryToken>)> WalkTree(PageTreeNode node, List<DictionaryToken> parents=null)
internal static IEnumerable<(DictionaryToken, IReadOnlyList<DictionaryToken>)> WalkTree(PageTreeNode node, List<DictionaryToken> parents=null)
{
if (parents == null)
{