using System; using System.Diagnostics; using System.Drawing; using System.Xml; using PDFPatcher.Common; namespace PDFPatcher.Model { public sealed class PdfInfoXmlDocument : XmlDocument { /// 返回已经初始化的 实例。 public PdfInfoXmlDocument() { Init(); } /// 获取或设置配置文件关联的 PDF 文件路径。 public string PdfDocumentPath { get => DocumentElement.GetAttribute(Constants.Info.DocumentPath); set => DocumentElement.SetAttribute(Constants.Info.DocumentPath, value); } /// 返回文档信息节点。 public DocumentInfoElement InfoNode => DocumentElement.GetOrCreateElement(Constants.Info.ThisName) as DocumentInfoElement; /// 返回页码标签节点。 public XmlElement PageLabelRoot => DocumentElement.GetOrCreateElement(Constants.PageLabels); public XmlNodeList PageLabels => DocumentElement.SelectNodes(Constants.PageLabels + "[1]/" + Constants.PageLabelsAttributes.Style); /// 返回书签根节点。 public BookmarkRootElement BookmarkRoot => DocumentElement.GetOrCreateElement(Constants.DocumentBookmark) as BookmarkRootElement; /// 获取根书签。 public XmlNodeList Bookmarks => DocumentElement.SelectNodes(Constants.DocumentBookmark + "[1]/" + Constants.Bookmark); private void Init() { var root = DocumentElement ?? AppendChild(CreateElement(Constants.PdfInfo)) as XmlElement; root.SetAttribute(Constants.Info.ProductName, System.Windows.Forms.Application.ProductName); root.SetAttribute(Constants.Info.ProductVersion, Constants.InfoDocVersion); root.SetAttribute(Constants.Info.ExportDate, DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss")); } public BookmarkElement CreateBookmark() { return new BookmarkElement(this); } public BookmarkElement CreateBookmark(BookmarkSettings settings) { var b = new BookmarkElement(this) { Title = settings.Title, IsOpen = settings.IsOpened, Action = Constants.ActionType.Goto }; if (settings.ForeColor.IsEmptyOrTransparent() == false) { b.ForeColor = settings.ForeColor; } if (settings.IsBold || settings.IsItalic) { b.TextStyle = (settings.IsBold ? FontStyle.Bold : FontStyle.Regular) | (settings.IsItalic ? FontStyle.Italic : FontStyle.Regular); } return b; } public PageLabelElement CreatePageLabel(MuPdfSharp.PageLabel label) { var l = new PageLabelElement(this); l.SetAttributes(label); return l; } public override XmlElement CreateElement(string prefix, string localName, string namespaceURI) { if (String.IsNullOrEmpty(prefix) && String.IsNullOrEmpty(namespaceURI)) { switch (localName) { case Constants.Bookmark: return new BookmarkElement(this); case Constants.DocumentBookmark: return new BookmarkRootElement(this); case Constants.PageLabelsAttributes.Style: return new PageLabelElement(this); case Constants.Info.ThisName: return new DocumentInfoElement(this); } } return base.CreateElement(prefix, localName, namespaceURI); } } /// 文档元数据属性元素。 public sealed class DocumentInfoElement : XmlElement { internal DocumentInfoElement(XmlDocument doc) : base(String.Empty, Constants.Info.ThisName, String.Empty, doc) { } public string Title { get => this.GetValue(Constants.Info.Title); set => this.SetValue(Constants.Info.Title, value, null); } public string Author { get => this.GetValue(Constants.Info.Author); set => this.SetValue(Constants.Info.Author, value, null); } public string Creator { get => this.GetValue(Constants.Info.Creator); set => this.SetValue(Constants.Info.Creator, value, null); } public string Keywords { get => this.GetValue(Constants.Info.Keywords); set => this.SetValue(Constants.Info.Keywords, value, null); } public string Producer { get => this.GetValue(Constants.Info.Producer); set => this.SetValue(Constants.Info.Producer, value, null); } public string Subject { get => this.GetValue(Constants.Info.Subject); set => this.SetValue(Constants.Info.Subject, value, null); } } public abstract class BookmarkContainer : XmlElement { protected BookmarkContainer(string name, XmlDocument doc) : base(String.Empty, name, String.Empty, doc) { } /// 获取当前书签容器是否有子书签。 public bool HasSubBookmarks => HasChildNodes && SelectSingleNode(Constants.Bookmark) != null; /// 获取当前书签容器的子书签。 public XmlNodeList SubBookmarks => SelectNodes(Constants.Bookmark); public BookmarkElement ParentBookmark => ParentNode as BookmarkElement; public BookmarkContainer Parent => ParentNode as BookmarkContainer; /// 创建新的下级书签并返回该书签。 public BookmarkElement AppendBookmark() { return AppendChild((OwnerDocument as PdfInfoXmlDocument).CreateBookmark()) as BookmarkElement; } /// 使用指定的配置创建新的书签。返回新创建的书签。 /// 书签设置。 public BookmarkElement AppendBookmark(BookmarkSettings settings) { return AppendChild((OwnerDocument as PdfInfoXmlDocument).CreateBookmark(settings)) as BookmarkElement; } } /// 书签的根元素。 public sealed class BookmarkRootElement : BookmarkContainer { internal BookmarkRootElement(XmlDocument doc) : base(Constants.DocumentBookmark, doc) { } } /// 书签元素。 [DebuggerDisplay(Constants.Bookmark + ":{Title}")] public sealed class BookmarkElement : BookmarkContainer { /// 在自动生成书签时标记级别的属性。 internal int AutoLevel = 0; /// 获取或设置书签的文本。 public string Title { get => GetAttribute(Constants.BookmarkAttributes.Title); set => SetAttribute(Constants.BookmarkAttributes.Title, value); } /// 获取或设置书签的颜色。 public Color ForeColor { get { if (HasAttribute(Constants.Colors.Red) || HasAttribute(Constants.Colors.Green) || HasAttribute(Constants.Colors.Blue)) { float r = this.GetValue(Constants.Colors.Red, 0f), g = this.GetValue(Constants.Colors.Green, 0f), b = this.GetValue(Constants.Colors.Blue, 0f); return Color.FromArgb((int)(r * 255f), (int)(g * 255f), (int)(b * 255f)); } else if (HasAttribute(Constants.Color)) { var a = GetAttribute(Constants.Color); int c = a.ToInt32(Int32.MaxValue); return c != Int32.MaxValue ? Color.FromArgb(c) : Color.FromName(a); } return Color.Transparent; } set { RemoveAttribute(Constants.Color); if (value == Color.Transparent) { return; } SetAttribute(Constants.Color, value.ToArgb().ToText()); } } /// 获取或设置书签的文本样式。 public FontStyle TextStyle { get { var s = GetAttribute(Constants.BookmarkAttributes.Style); if (String.IsNullOrEmpty(s) == false) { switch (s) { case Constants.BookmarkAttributes.StyleType.Bold: return FontStyle.Bold; case Constants.BookmarkAttributes.StyleType.Italic: return FontStyle.Italic; case Constants.BookmarkAttributes.StyleType.BoldItalic: return FontStyle.Italic | FontStyle.Bold; } } return FontStyle.Regular; } set { string s; switch (value) { case FontStyle.Bold: s = Constants.BookmarkAttributes.StyleType.Bold; break; case FontStyle.Italic: s = Constants.BookmarkAttributes.StyleType.Italic; break; case FontStyle.Bold | FontStyle.Italic: s = Constants.BookmarkAttributes.StyleType.BoldItalic; break; case FontStyle.Regular: case FontStyle.Underline: case FontStyle.Strikeout: default: RemoveAttribute(Constants.BookmarkAttributes.Style); return; } SetAttribute(Constants.BookmarkAttributes.Style, s); } } /// 获取或设置书签的默认打开状态。 public bool IsOpen { get { if (HasChildNodes == false) { return false; } return GetAttribute(Constants.BookmarkAttributes.Open) == Constants.Boolean.True; } set { //if (HasSubBookmarks == false) { // return; //} if (value) { SetAttribute(Constants.BookmarkAttributes.Open, Constants.Boolean.True); } else { RemoveAttribute(Constants.BookmarkAttributes.Open); } } } /// 获取或设置目标动作。 public string Action { get => this.GetValue(Constants.DestinationAttributes.Action, Constants.ActionType.Goto); set => this.SetValue(Constants.DestinationAttributes.Action, value); } /// 获取或设置书签的目标页面。 public int Page { get => this.GetValue(Constants.DestinationAttributes.Page, 0); set { this.SetValue(Constants.DestinationAttributes.Page, value, 0); if (HasAttribute(Constants.DestinationAttributes.Action) == false) { SetAttribute(Constants.DestinationAttributes.Action, Constants.ActionType.Goto); } } } /// 返回或设置目标视图。 public string DestinationView { get => GetAttribute(Constants.DestinationAttributes.View); set => this.SetValue(Constants.DestinationAttributes.View, value); } /// 获取或设置 XYZ 目标视图下的缩放比例。 public float ScaleFactor { get => this.GetValue(Constants.Coordinates.ScaleFactor, 1f); set { SetAttribute(Constants.Coordinates.ScaleFactor, value.ToText()); SetAttribute(Constants.DestinationAttributes.View, Constants.DestinationAttributes.ViewType.XYZ); } } /// 获取或设置跳转目标的上坐标。 public float Top { get => this.GetValue(Constants.Coordinates.Top, 0f); set => this.SetValue(Constants.Coordinates.Top, value, 0); } /// 获取或设置跳转目标的左坐标。 public float Left { get => this.GetValue(Constants.Coordinates.Left, 0f); set => this.SetValue(Constants.Coordinates.Left, value, 0); } /// 获取或设置跳转目标的下坐标。 public float Bottom { get => this.GetValue(Constants.Coordinates.Bottom, 0f); set => this.SetValue(Constants.Coordinates.Bottom, value, 0); } /// 获取或设置跳转目标的右坐标。 public float Right { get => this.GetValue(Constants.Coordinates.Right, 0f); set => this.SetValue(Constants.Coordinates.Right, value, 0); } public int MarkerColor { get => this.GetValue("标记颜色", 0); set => this.SetValue("标记颜色", value, 0); } internal BookmarkElement(XmlDocument doc) : base(Constants.Bookmark, doc) { } /// 设置跳转到页面的书签动作。 /// 书签的标题。 /// 跳转页面。 /// 跳转位置。 public void SetTitleAndGotoPagePosition(string title, int pageNumber, float position) { SetAttribute(Constants.BookmarkAttributes.Title, title); this.SetValue(Constants.DestinationAttributes.Page, pageNumber, 0); SetAttribute(Constants.DestinationAttributes.Action, Constants.ActionType.Goto); if (position != 0) { SetAttribute(Constants.DestinationAttributes.View, Constants.DestinationAttributes.ViewType.XYZ); this.SetValue(Constants.Coordinates.Top, position, 0); } } } /// 页码标签设置集合的根元素。 public sealed class PageLabelRootElement : XmlElement { internal PageLabelRootElement(XmlDocument doc) : base(String.Empty, Constants.DocumentBookmark, String.Empty, doc) { } public XmlNodeList Labels => SelectNodes(Constants.PageLabelsAttributes.Style); public void Add(MuPdfSharp.PageLabel label) { foreach (PageLabelElement item in Labels) { if (item.PageNumber == label.FromPageNumber) { item.SetAttributes(label); return; } } (this.AppendElement(Constants.PageLabelsAttributes.Style) as PageLabelElement).SetAttributes(label); } } /// 页码标签设置元素。 public sealed class PageLabelElement : XmlElement { /// 获取或指定开始使用页码标签的绝对页码。 public int PageNumber { get => GetAttribute(Constants.PageLabelsAttributes.PageNumber).ToInt32(); set => this.SetValue(Constants.PageLabelsAttributes.PageNumber, value < 1 ? 0 : value, 0); } public string PrefixLabel { get => GetAttribute(Constants.PageLabelsAttributes.Prefix); set => this.SetValue(Constants.PageLabelsAttributes.Prefix, value); } /// 获取或指定页码标签样式。 public string Style { get => GetAttribute(Constants.PageLabelsAttributes.Style); set => this.SetValue(Constants.PageLabelsAttributes.Style, value, Constants.PageLabelStyles.Names[0]); } /// 获取或指定页码标签的起始编号。 public int StartNumber { get => GetAttribute(Constants.PageLabelsAttributes.StartPage).ToInt32(); set => this.SetValue(Constants.PageLabelsAttributes.StartPage, value < 1 ? 0 : value, 0); } internal PageLabelElement(XmlDocument doc) : base(String.Empty, Constants.PageLabelsAttributes.Style, String.Empty, doc) { } public void SetAttributes(MuPdfSharp.PageLabel label) { this.SetValue(Constants.PageLabelsAttributes.PageNumber, label.FromPageNumber + 1, 0); SetAttribute(Constants.PageLabelsAttributes.Style, ValueHelper.MapValue((char)label.NumericStyle, Constants.PageLabelStyles.PdfValues, Constants.PageLabelStyles.Names)); this.SetValue(Constants.PageLabelsAttributes.StartPage, label.StartAt, 0); this.SetValue(Constants.PageLabelsAttributes.Prefix, label.Prefix); } public MuPdfSharp.PageLabel ToPageLabel() { return new MuPdfSharp.PageLabel( PageNumber - 1, StartNumber, PrefixLabel, (MuPdfSharp.PageLabelStyle)ValueHelper.MapValue(Style, Constants.PageLabelStyles.Names, Constants.PageLabelStyles.PdfValues)); } } }