using System; using System.Collections.Generic; using System.Drawing; using System.Text; using PDFPatcher.Common; using MuPdfSharp; using DrawingPoint = System.Drawing.Point; namespace PDFPatcher.Functions.Editor { public enum ContentDirection { TopToDown, RightToLeft } public enum MouseMode { Move, Selection } public readonly struct PagePoint { public static readonly PagePoint Empty; public readonly int Page; public readonly float ImageX, ImageY; public PagePoint(int pageNumber, float imageX, float imageY) { Page = pageNumber; ImageX = imageX; ImageY = imageY; } } public readonly struct PagePosition { public static readonly PagePosition Empty; /// /// 所在页码。 /// public readonly int Page; /// /// 在 PDF 页面空间上的位置。 /// public readonly float PageX, PageY; /// /// 在渲染页面上的位置。 /// public readonly int ImageX, ImageY; /// /// 当前点是否在页面上。 /// public readonly bool IsInPage; public MuPdfSharp.Point Location => new MuPdfSharp.Point(PageX, PageY); internal PagePosition(int page, PointF position, DrawingPoint imagePosition, bool isInPage) : this(page, position.X, position.Y, imagePosition.X, imagePosition.Y, isInPage) { } internal PagePosition(int page, float x, float y, int imageX, int imageY, bool isInPage) { Page = page; PageX = x; PageY = y; ImageX = imageX; ImageY = imageY; IsInPage = isInPage; } } public readonly struct PageRegion { public static readonly PageRegion Empty = new PageRegion(); public readonly int Page; public readonly MuPdfSharp.Rectangle Region; internal PageRegion(PagePosition p1, PagePosition p2) { if (p1.Page != p2.Page) { Page = 0; Region = new MuPdfSharp.Rectangle(); } else { Page = p1.Page; Region = new MuPdfSharp.Rectangle(p1.PageX, p1.PageY, p2.PageX, p2.PageY); } } } public readonly struct TextInfo : IMuTextLines, IMuTextSpans, IMuBoundedElement { public readonly MuPage Page; /// 获取文本字符的位置边框。 public readonly MuPdfSharp.Rectangle TextBBox; /// 获取文本位置以下的文本行。 public readonly List Lines; public readonly List Spans; public TextInfo(MuPage page, MuPdfSharp.Rectangle bbox, List textLines, List spans) { Page = page; TextBBox = bbox; Lines = textLines; Spans = spans; } IEnumerable IMuTextLines.Lines => Lines; public MuPdfSharp.Rectangle BBox => TextBBox; IEnumerable IMuTextSpans.Spans => Spans; public IEnumerable GetFonts() { if (Spans.HasContent() == false) { yield break; } HashSet fonts = new HashSet(); foreach (var span in Spans) { if (fonts.Add(span.FontID)) { yield return Page.GetFont(span); } } } public IEnumerable GetFontNames() { if (Spans.HasContent() == false) { yield break; } HashSet fonts = new HashSet(); foreach (var span in Spans) { var f = Page.GetFont(span); if (fonts.Add(f.Name)) { yield return f.Name; } } } public override string ToString() { if (Lines == null) { return null; } var c = Lines.Count; if (c == 1) { return Lines[0].Text; } var sb = new StringBuilder(); var b = Lines[0].BBox; foreach (var line in Lines) { if (line.BBox.IsHorizontalNeighbor(b)) { sb.Append(line.Text); b = b.Union(line.BBox); } else { b = line.BBox; sb.AppendLine(); sb.Append(line.Text); } } return sb.ToString(); } } public readonly struct Selection { readonly RenderResultCache _cache; public static readonly Selection Empty; /// /// 获取选中区域的页码。 /// public readonly int Page; /// /// 获取选中区域在页面上的矩形区域(屏幕左下角点坐标为0,0)。 /// public readonly MuPdfSharp.Rectangle PageRegion; /// /// 获取选中区域在显示图片上的矩形区域。 /// public readonly RectangleF ImageRegion; public Bitmap GetSelectedBitmap() { _cache.LoadPage(Page); var p = _cache.GetBitmap(Page); var clip = new MuPdfSharp.Rectangle( ImageRegion.Left < 0 ? 0 : ImageRegion.Left, ImageRegion.Top < 0 ? 0 : ImageRegion.Top, ImageRegion.Right > p.Width ? p.Width : ImageRegion.Right, ImageRegion.Bottom > p.Height ? p.Height : ImageRegion.Bottom ); return p.Clone(clip, p.PixelFormat); } public Selection(RenderResultCache cache, int page, MuPdfSharp.Rectangle region, RectangleF imageRegion) { Page = page; PageRegion = region; ImageRegion = imageRegion; _cache = cache; } } }