mirror of
https://github.com/wmjordan/PDFPatcher.git
synced 2026-10-18 13:42:28 +08:00
200 lines
7.4 KiB
C#
200 lines
7.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Xml;
|
|
using iTextSharp.text.pdf;
|
|
using PDFPatcher.Common;
|
|
using PDFPatcher.Model;
|
|
|
|
namespace PDFPatcher.Processor
|
|
{
|
|
internal sealed class PdfActionExporter
|
|
{
|
|
readonly Common.UnitConverter _unitConverter;
|
|
|
|
public PdfActionExporter(Common.UnitConverter unitConverter) {
|
|
_unitConverter = unitConverter;
|
|
}
|
|
|
|
internal void ExportFileLocation(XmlWriter w, PdfObject file) {
|
|
if (file.Type == PdfObject.DICTIONARY) {
|
|
var fs = file as PdfDictionary;
|
|
if (fs.Contains(PdfName.UF)) {
|
|
w.WriteAttributeString(Constants.DestinationAttributes.Path, PdfHelper.GetValidXmlString(fs.GetAsString(PdfName.UF).ToUnicodeString()));
|
|
}
|
|
else if (fs.Contains(PdfName.F)) {
|
|
file = fs.Get(PdfName.F);
|
|
}
|
|
}
|
|
else if (file.Type == PdfObject.STRING)
|
|
w.WriteAttributeString(Constants.DestinationAttributes.Path, PdfHelper.GetValidXmlString(((PdfString)file).Decode(System.Text.Encoding.Default)));
|
|
}
|
|
|
|
internal void ExportAction(PdfDictionary action, Dictionary<int, int> pageRefMap, XmlWriter target) {
|
|
PdfObject dest;
|
|
if (action == null)
|
|
return;
|
|
var actionType = PdfReader.GetPdfObjectRelease(action.Get(PdfName.S));
|
|
if (PdfName.GOTO.Equals(actionType)) {
|
|
dest = PdfReader.GetPdfObjectRelease(action.Get(PdfName.D));
|
|
if (dest != null) {
|
|
ExportGotoAction(dest, target, pageRefMap);
|
|
}
|
|
}
|
|
else if (PdfName.URI.Equals(actionType)) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Action, Constants.ActionType.Uri);
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Path, PdfHelper.GetValidXmlString(action.Locate<PdfString>(PdfName.URI).ToUnicodeString()));
|
|
}
|
|
else if (PdfName.GOTOR.Equals(actionType)) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Action, Constants.ActionType.GotoR);
|
|
dest = PdfReader.GetPdfObjectRelease(action.Get(PdfName.D));
|
|
if (dest != null) {
|
|
if (dest.IsString())
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Named, PdfHelper.GetValidXmlString(dest.ToString()));
|
|
else if (dest.IsName())
|
|
target.WriteAttributeString(Constants.DestinationAttributes.NamedN, PdfName.DecodeName(dest.ToString()));
|
|
else if (dest.IsArray()) {
|
|
var arr = (PdfArray)dest;
|
|
if (arr.Size > 0 && arr[0].IsNumber()) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Page, PdfHelper.GetValidXmlString(((arr[0] as PdfNumber).IntValue + 1).ToText()));
|
|
ExportDestinationView(target, arr);
|
|
}
|
|
}
|
|
}
|
|
var file = action.Locate<PdfObject>(PdfName.F) ?? action.Locate<PdfObject>(PdfName.WIN);
|
|
if (file != null) {
|
|
ExportFileLocation(target, file);
|
|
}
|
|
var newWindow = action.Locate<PdfBoolean>(PdfName.NEWWINDOW);
|
|
if (newWindow != null)
|
|
target.WriteAttributeString(Constants.DestinationAttributes.NewWindow, newWindow.BooleanValue ? Constants.Boolean.True : Constants.Boolean.False);
|
|
}
|
|
else if (PdfName.LAUNCH.Equals(actionType)) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Action, Constants.ActionType.Launch);
|
|
var file = PdfReader.GetPdfObjectRelease(action.Get(PdfName.F)) ?? PdfReader.GetPdfObjectRelease(action.Get(PdfName.WIN));
|
|
if (file != null) {
|
|
ExportFileLocation(target, file);
|
|
}
|
|
}
|
|
else if (PdfName.JAVASCRIPT.Equals(actionType)) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Action, Constants.ActionType.Javascript);
|
|
target.WriteAttributeString(Constants.DestinationAttributes.ScriptContent, PdfReader.GetPdfObjectRelease(action.Get(PdfName.JS)).ToString());
|
|
}
|
|
}
|
|
|
|
internal void ExportGotoAction(PdfObject dest, XmlWriter target, Dictionary<int, int> pages) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Action, Constants.ActionType.Goto);
|
|
if (dest.Type == PdfObject.STRING)
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Named, StringHelper.ReplaceControlAndBomCharacters((dest as PdfString).ToUnicodeString()));
|
|
else if (dest.Type == PdfObject.NAME)
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Named, PdfName.DecodeName(dest.ToString()));
|
|
else if (dest.Type == PdfObject.ARRAY) {
|
|
var a = dest as PdfArray;
|
|
if (a.Size > 0) {
|
|
var p = a[0];
|
|
int pn = 0;
|
|
if (p.Type == PdfObject.INDIRECT && pages.TryGetValue(GetNumber((PdfIndirectReference)a[0]), out pn)) {
|
|
// use pn
|
|
}
|
|
else if (p.Type == PdfObject.NUMBER) {
|
|
pn = (p as PdfNumber).IntValue + 1;
|
|
}
|
|
if (pn > 0) {
|
|
target.WriteAttributeString(Constants.DestinationAttributes.Page, pn.ToText());
|
|
}
|
|
}
|
|
ExportDestinationView(target, a);
|
|
}
|
|
}
|
|
|
|
private void ExportDestinationView(XmlWriter target, PdfArray dest) {
|
|
if (dest.Size < 2) {
|
|
return;
|
|
}
|
|
var pn = dest[1] as PdfName;
|
|
if (pn == null) {
|
|
return;
|
|
}
|
|
var m = PdfHelper.GetPdfFriendlyName(pn);
|
|
target.WriteAttributeString(Constants.DestinationAttributes.View, m);
|
|
var p = new string[dest.Size - 2];
|
|
PdfObject o;
|
|
for (int i = 0; i < p.Length; i++) {
|
|
o = dest[i + 2];
|
|
if (o == null) {
|
|
p[i] = String.Empty;
|
|
}
|
|
p[i] = (o.Type == PdfObject.NUMBER) ? (m == Constants.DestinationAttributes.ViewType.XYZ && i == 2
|
|
? ((PdfNumber)o).FloatValue
|
|
: _unitConverter.FromPoint(((PdfNumber)o).FloatValue)).ToText(
|
|
)
|
|
: (o.Type == PdfObject.NULL) ? Constants.Coordinates.Unchanged
|
|
: o.ToString();
|
|
}
|
|
switch (m) {
|
|
case Constants.DestinationAttributes.ViewType.XYZ:
|
|
if (p.Length < 1) {
|
|
goto default;
|
|
}
|
|
target.WriteAttributeString(Constants.Coordinates.Left, p[0]);
|
|
if (p.Length > 1) {
|
|
target.WriteAttributeString(Constants.Coordinates.Top, p[1]);
|
|
}
|
|
if (p.Length > 2) {
|
|
target.WriteAttributeString(Constants.Coordinates.ScaleFactor, p[2]);
|
|
}
|
|
break;
|
|
case Constants.DestinationAttributes.ViewType.Fit:
|
|
case Constants.DestinationAttributes.ViewType.FitB:
|
|
break;
|
|
case Constants.DestinationAttributes.ViewType.FitBH:
|
|
case Constants.DestinationAttributes.ViewType.FitH:
|
|
if (p.Length < 1) {
|
|
goto default;
|
|
}
|
|
target.WriteAttributeString(Constants.Coordinates.Top, p[0]);
|
|
break;
|
|
case Constants.DestinationAttributes.ViewType.FitV:
|
|
case Constants.DestinationAttributes.ViewType.FitBV:
|
|
if (p.Length < 1) {
|
|
goto default;
|
|
}
|
|
target.WriteAttributeString(Constants.Coordinates.Left, p[0]);
|
|
break;
|
|
case Constants.DestinationAttributes.ViewType.FitR:
|
|
if (p.Length < 1) {
|
|
goto default;
|
|
}
|
|
target.WriteAttributeString(Constants.Coordinates.Left, p[0]);
|
|
if (p.Length > 1) {
|
|
target.WriteAttributeString(Constants.Coordinates.Bottom, p[1]);
|
|
}
|
|
if (p.Length > 2) {
|
|
target.WriteAttributeString(Constants.Coordinates.Right, p[2]);
|
|
}
|
|
if (p.Length > 3) {
|
|
target.WriteAttributeString(Constants.Coordinates.Top, p[3]);
|
|
}
|
|
break;
|
|
default:
|
|
System.Diagnostics.Trace.WriteLine("目标位置无效");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static int GetNumber(PdfIndirectReference indirect) {
|
|
var pdfObj = (PdfDictionary)PdfReader.GetPdfObjectRelease(indirect);
|
|
if (pdfObj == null) {
|
|
return 0;
|
|
}
|
|
if (pdfObj.Contains(PdfName.TYPE)
|
|
&& PdfName.PAGES.Equals(pdfObj.GetAsName(PdfName.TYPE))
|
|
&& pdfObj.Contains(PdfName.KIDS)) {
|
|
var kids = (PdfArray)pdfObj.Get(PdfName.KIDS);
|
|
indirect = (PdfIndirectReference)kids[0];
|
|
}
|
|
return indirect.Number;
|
|
}
|
|
|
|
}
|
|
}
|