using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.IO; using System.Text; namespace PdfiumViewer.Demo { public class PdfRangeDocument : IPdfDocument { public static PdfRangeDocument FromDocument(IPdfDocument document, int startPage, int endPage) { if (document == null) throw new ArgumentNullException(nameof(document)); if (endPage < startPage) throw new ArgumentException("End page cannot be less than start page"); if (startPage < 0) throw new ArgumentException("Start page cannot be less than zero"); if (endPage >= document.PageCount) throw new ArgumentException("End page cannot be more than the number of pages in the document"); return new PdfRangeDocument( document, startPage, endPage ); } private readonly IPdfDocument _document; private readonly int _startPage; private readonly int _endPage; private PdfBookmarkCollection _bookmarks; private IList _sizes; private PdfRangeDocument(IPdfDocument document, int startPage, int endPage) { _document = document; _startPage = startPage; _endPage = endPage; } public int PageCount { get { return _endPage - _startPage + 1; } } public PdfBookmarkCollection Bookmarks { get { if (_bookmarks == null) _bookmarks = TranslateBookmarks(_document.Bookmarks); return _bookmarks; } } private PdfBookmarkCollection TranslateBookmarks(PdfBookmarkCollection bookmarks) { var result = new PdfBookmarkCollection(); TranslateBookmarks(result, bookmarks); return result; } private void TranslateBookmarks(PdfBookmarkCollection result, PdfBookmarkCollection bookmarks) { foreach (var bookmark in bookmarks) { if (bookmark.PageIndex >= _startPage && bookmark.PageIndex <= _endPage) { var resultBookmark = new PdfBookmark { PageIndex = bookmark.PageIndex - _startPage, Title = bookmark.Title }; TranslateBookmarks(resultBookmark.Children, bookmark.Children); result.Add(resultBookmark); } } } public IList PageSizes { get { if (_sizes == null) _sizes = TranslateSizes(_document.PageSizes); return _sizes; } } private IList TranslateSizes(IList pageSizes) { var result = new List(); for (int i = _startPage; i <= _endPage; i++) { result.Add(pageSizes[i]); } return result; } public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangle bounds, bool forPrinting) { _document.Render(TranslatePage(page), graphics, dpiX, dpiY, bounds, forPrinting); } public void Render(int page, Graphics graphics, float dpiX, float dpiY, Rectangle bounds, PdfRenderFlags flags) { _document.Render(TranslatePage(page), graphics, dpiX, dpiY, bounds, flags); } public Image Render(int page, float dpiX, float dpiY, bool forPrinting) { return _document.Render(TranslatePage(page), dpiX, dpiY, forPrinting); } public Image Render(int page, float dpiX, float dpiY, PdfRenderFlags flags) { return _document.Render(TranslatePage(page), dpiX, dpiY, flags); } public Image Render(int page, int width, int height, float dpiX, float dpiY, bool forPrinting) { return _document.Render(TranslatePage(page), width, height, dpiX, dpiY, forPrinting); } public Image Render(int page, int width, int height, float dpiX, float dpiY, PdfRenderFlags flags) { return _document.Render(TranslatePage(page), width, height, dpiX, dpiY, flags); } public Image Render(int page, int width, int height, float dpiX, float dpiY, PdfRotation rotate, PdfRenderFlags flags) { return _document.Render(page, width, height, dpiX, dpiY, rotate, flags); } public void Save(string path) { _document.Save(path); } public void Save(Stream stream) { _document.Save(stream); } public PdfMatches Search(string text, bool matchCase, bool wholeWord) { return TranslateMatches(_document.Search(text, matchCase, wholeWord)); } public PdfMatches Search(string text, bool matchCase, bool wholeWord, int page) { return TranslateMatches(_document.Search(text, matchCase, wholeWord, page)); } public PdfMatches Search(string text, bool matchCase, bool wholeWord, int startPage, int endPage) { return TranslateMatches(_document.Search(text, matchCase, wholeWord, startPage, endPage)); } private PdfMatches TranslateMatches(PdfMatches search) { if (search == null) return null; var matches = new List(); foreach (var match in search.Items) { matches.Add(new PdfMatch( match.Text, new PdfTextSpan(match.TextSpan.Page + _startPage, match.TextSpan.Offset, match.TextSpan.Length), match.Page + _startPage )); } return new PdfMatches( search.StartPage + _startPage, search.EndPage + _startPage, matches ); } public PrintDocument CreatePrintDocument() { return _document.CreatePrintDocument(); } public PrintDocument CreatePrintDocument(PdfPrintMode printMode) { return _document.CreatePrintDocument(printMode); } public PrintDocument CreatePrintDocument(PdfPrintSettings settings) { return _document.CreatePrintDocument(settings); } public PdfPageLinks GetPageLinks(int pageNumber, Size pageSize) { return TranslateLinks(_document.GetPageLinks(pageNumber + _startPage, pageSize)); } private PdfPageLinks TranslateLinks(PdfPageLinks pageLinks) { if (pageLinks == null) return null; var links = new List(); foreach (var link in pageLinks.Links) { links.Add(new PdfPageLink( link.Bounds, link.TargetPage + _startPage, link.Uri )); } return new PdfPageLinks(links); } public void DeletePage(int pageNumber) { _document.DeletePage(TranslatePage(pageNumber)); } public void RotatePage(int pageNumber, PdfRotation rotation) { _document.RotatePage(TranslatePage(pageNumber), rotation); } public PdfInformation GetInformation() { return _document.GetInformation(); } public string GetPdfText(int page) { return _document.GetPdfText(TranslatePage(page)); } public string GetPdfText(PdfTextSpan textSpan) { return _document.GetPdfText(textSpan); } public IList GetTextBounds(PdfTextSpan textSpan) { var result = new List(); foreach (var rectangle in _document.GetTextBounds(textSpan)) { result.Add(new PdfRectangle( rectangle.Page + _startPage, rectangle.Bounds )); } return result; } public PointF PointToPdf(int page, Point point) { return _document.PointToPdf(TranslatePage(page), point); } public Point PointFromPdf(int page, PointF point) { return _document.PointFromPdf(TranslatePage(page), point); } public RectangleF RectangleToPdf(int page, Rectangle rect) { return _document.RectangleToPdf(TranslatePage(page), rect); } public Rectangle RectangleFromPdf(int page, RectangleF rect) { return _document.RectangleFromPdf(TranslatePage(page), rect); } private int TranslatePage(int page) { if (page < 0 || page >= PageCount) throw new ArgumentException("Page number out of range"); return page + _startPage; } public void Dispose() { _document.Dispose(); } } }