Files
2025-08-25 19:59:39 +08:00

169 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using CLR;
using iTextSharp.text.pdf;
namespace PDFPatcher.Model
{
static class PdfModelHelper
{
internal static T Locate<T>(this PdfDictionary source, params object[] path) where T : PdfObject {
PdfObject s = source;
if (s == null) {
return null;
}
PdfName n;
foreach (var item in path) {
n = item as PdfName;
if (s == null) {
return null;
}
if (n != null) {
if (s.Type != PdfObject.DICTIONARY && s.Type != PdfObject.STREAM) {
return null;
}
s = ((PdfDictionary)s).GetDirectObject(n);
continue;
}
if (item is not int) {
throw new ArgumentException("参数类型必须为 Int32 或 PdfName");
}
int i = (int)item;
if (s.Type != PdfObject.ARRAY) {
return null;
}
s = ((PdfArray)s).GetDirectObject(i);
}
return s as T;
}
internal static T Locate<T>(this PdfDictionary source, params PdfName[] path) where T : PdfObject {
return source.Locate<T>(true, path);
}
internal static T Locate<T>(this PdfDictionary source, bool resolveRef, params PdfName[] path) where T : PdfObject {
PdfObject o = null;
foreach (var item in path) {
if (source == null) {
return null;
}
o = resolveRef ? source.GetDirectObject(item) : source.Get(item);
source = o as PdfDictionary;
}
return o as T;
}
internal static T Locate<T>(this PdfArray source, int index) where T : PdfObject {
return source.Locate<T>(true, index);
}
internal static T Locate<T>(this PdfArray source, bool resolveRef, int index) where T : PdfObject {
if (source == null) {
return null;
}
return (resolveRef ? source.GetDirectObject(index) : source[index]) as T;
}
internal static T CastAs<T>(this PdfIndirectReference pdfRef) where T : PdfObject {
return PdfReader.GetPdfObject(pdfRef) as T;
}
internal static float ValueAsFloat(this PdfObject obj) {
return obj is PdfNumber n
? n.FloatValue
: 0;
}
internal static float ValueAsInt(this PdfObject obj) {
return obj is PdfNumber n
? n.IntValue
: 0;
}
internal static bool ValueIs(this PdfNumber obj, double value) {
return obj != null && obj.DoubleValue == value;
}
internal static bool ValueIs(this PdfBoolean obj, bool value) {
return obj != null && obj.BooleanValue == value;
}
internal static bool ValueIs(this PdfObject obj, PdfName value) {
return value.Equals(obj);
}
internal static int TryGetInt32(this PdfDictionary source, PdfName key, int defaultValue) {
var w = source.GetAsNumber(key);
return w?.IntValue ?? defaultValue;
}
internal static bool TryGetBoolean(this PdfDictionary source, PdfName key, bool defaultValue) {
var b = source.GetAsBoolean(key);
return b?.BooleanValue ?? defaultValue;
}
internal static string Decode(this PdfString text, Encoding encoding) {
if (text == null) {
return String.Empty;
}
var bytes = text.GetBytes();
using (var ms = new MemoryStream(bytes)) {
if (encoding == null) {
if (bytes.Length >= 2 && Op.Cast<byte, ushort>(ref bytes[0]).CeqAny(0xFFFE, 0xFEFF)) {
// bytes 以 0xFEFF 或 0xFFFE 开头
using (var r = new StreamReader(ms, true)) {
return r.ReadToEnd();
}
}
else {
return PdfEncodings.ConvertToString(bytes, PdfObject.TEXT_PDFDOCENCODING);
}
}
else {
// 跳过字节顺序标记
if (bytes.Length >= 2 && Op.Cast<byte, ushort>(ref bytes[0]).CeqAny(0xFFFE, 0xFEFF)) {
// bytes 以 0xFEFF 或 0xFFFE 开头
ms.Position += 2;
}
else if (bytes.Length >= 3 && bytes[0] == 0xef && bytes[1] == 0xbb && bytes[2] == 0xbf) {
ms.Position += 3;
}
else if (bytes.Length >= 4 && Op.Cast<byte, uint>(ref bytes[0]) == 0xFFFE0000) {
// bytes 以 0000FEFF 开头
ms.Position += 4;
}
using (var r = new StreamReader(ms, encoding)) {
return r.ReadToEnd();
}
}
}
}
internal static PdfString ToPdfString(this string text) {
if (String.IsNullOrEmpty(text)) {
return new PdfString();
}
bool u = false;
foreach (var c in text) {
if (c > 127) {
u = true;
break;
}
}
return u ? new PdfString(text, PdfObject.TEXT_UNICODE) : new PdfString(text);
}
internal static IEnumerable<ResourceReference> GetReferencedResources(PdfDictionary source, Predicate<PdfDictionary> predicate, HashSet<PdfIndirectReference> refDedup) {
foreach (var item in source) {
if (item.Value is PdfIndirectReference r
&& refDedup.Add(r)
&& PdfReader.GetPdfObjectRelease(r) is PdfDictionary o) {
if (predicate(o)) {
yield return new ResourceReference(r, item.Key, o);
}
foreach (var f in GetReferencedResources(o, predicate, refDedup)) {
yield return f;
}
}
else if (item.Value is PdfDictionary d) {
foreach (var f in GetReferencedResources(d, predicate, refDedup)) {
yield return f;
}
}
}
}
}
}