/* * Copyright (C) 2013 FooProject * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; using Windows.Graphics.Display; using Windows.Graphics.Printing; using System.Runtime.InteropServices; using Windows.UI; using FooEditEngine.Metro; namespace FooEditEngine { /// /// イベントデータ /// public sealed class ParseCommandEventArgs { /// /// 印刷中のページ番号 /// public int PageNumber; /// /// ページ範囲内で許容されている最大の番号 /// public int MaxPageNumber; /// /// 処理前の文字列 /// public string Original; /// /// コンストラクター /// /// 印刷中のページ番号 /// 印刷すべき最大のページ番号 /// 処理前の文字列 public ParseCommandEventArgs(int nowPage, int maxPage, string org) { this.PageNumber = nowPage; this.MaxPageNumber = maxPage; this.Original = org; } } /// /// コマンド処理用デリゲート /// /// 送信元のクラス /// イベントデータ /// 処理後の文字列 public delegate string ParseCommandHandler(object sender, ParseCommandEventArgs e); sealed class PrintableViewFactory { Windows.UI.Color foreground, comment, keyword1, keyword2, literal, url; string fontName; double fontSize; LineBreakMethod lineBreakMethod; int lineBreakCharCount, tabCount; Document document; bool urlMark; IHilighter hilighter; float displayDpi; Padding padding; public PrintableViewFactory(FooTextBox textbox,Padding padding) { this.foreground = textbox.Foreground; this.comment = textbox.Comment; this.keyword1 = textbox.Keyword1; this.keyword2 = textbox.Keyword2; this.literal = textbox.Literal; this.url = textbox.URL; this.fontName = textbox.FontFamily.Source; this.fontSize = textbox.FontSize; this.tabCount = textbox.TabChars; this.document = textbox.Document; this.lineBreakMethod = textbox.LineBreakMethod; this.lineBreakCharCount = textbox.LineBreakCharCount; this.drawLineNumber = textbox.DrawLineNumber; this.urlMark = textbox.MarkURL; this.hilighter = textbox.Hilighter; this.displayDpi = DisplayInformation.GetForCurrentView().LogicalDpi; this.padding = padding; this.EnableHilight = true; } public D2DPrintRender CreateRender(PrintPageDescription pagedesc, IPrintDocumentPackageTarget docPackageTarget) { D2DPrintRender render; Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height); render = new D2DPrintRender(this.fontName, this.fontSize, size, Math.Min(pagedesc.DpiX, pagedesc.DpiY), docPackageTarget); render.Foreground = D2DRenderBase.ToColor4(this.foreground); render.Comment = D2DRenderBase.ToColor4(this.comment); render.Keyword1 = D2DRenderBase.ToColor4(this.keyword1); render.Keyword2 = D2DRenderBase.ToColor4(this.keyword2); render.Literal = D2DRenderBase.ToColor4(this.literal); render.Url = D2DRenderBase.ToColor4(this.url); return render; } public D2DPrintPreviewRender CreateRender(PrintPageDescription pagedesc) { D2DPrintPreviewRender render; Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height); render = new D2DPrintPreviewRender(this.fontName, this.fontSize, size, this.displayDpi); render.Foreground = D2DRenderBase.ToColor4(this.foreground); render.Comment = D2DRenderBase.ToColor4(this.comment); render.Keyword1 = D2DRenderBase.ToColor4(this.keyword1); render.Keyword2 = D2DRenderBase.ToColor4(this.keyword2); render.Literal = D2DRenderBase.ToColor4(this.literal); render.Url = D2DRenderBase.ToColor4(this.url); return render; } public PrintableView CreateView(PrintPageDescription pagedesc, IPrintableTextRender render, string header, string footer) { Document documentSnap = new Document(this.document); documentSnap.LayoutLines.Render = render; PrintableView view = new PrintableView(documentSnap, render,padding); view.Header = header; view.Footer = footer; view.PageBound = new Rectangle(pagedesc.ImageableRect.X, pagedesc.ImageableRect.Y, pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height); view.Hilighter = this.EnableHilight ? this.hilighter : null; documentSnap.DrawLineNumber = this.drawLineNumber; view.PerfomLayouts(); return view; } public bool drawLineNumber { get; set; } public bool EnableHilight { get; set; } } sealed class DocumentSource : IPrintDocumentPageSource, IPrintPreviewPageCollection, IPrintDocumentSource,IPrintPreviewSource { IPrintPreviewDxgiPackageTarget dxgiPreviewTarget; bool paginateCalled = false; Size imageRect; PrintableViewFactory factory; D2DPrintPreviewRender previewRender; PrintableView previewView; int maxPreviePageCount; public ParseCommandHandler ParseHF; public string Header = string.Empty; public string Fotter = string.Empty; public DocumentSource(FooTextBox textbox,Padding padding) { this.factory = new PrintableViewFactory(textbox, padding); } internal enum SyntaxHilightApplibility { Apply, NoApply, } [DisplayPrintOptionResourceID("SyntaxHilight")] internal SyntaxHilightApplibility EnableHilight { get { return this.factory.EnableHilight ? SyntaxHilightApplibility.Apply : SyntaxHilightApplibility.NoApply; } set { this.factory.EnableHilight = value == SyntaxHilightApplibility.Apply; } } internal enum LineNumberVisiblity { Visible, Hidden } [DisplayPrintOptionResourceID("ShowLineNumber")] internal LineNumberVisiblity ShowLineNumber { get { return this.factory.drawLineNumber ? LineNumberVisiblity.Visible : LineNumberVisiblity.Hidden; } set { this.factory.drawLineNumber = value == LineNumberVisiblity.Visible; } } public void GetPreviewPageCollection(IPrintDocumentPackageTarget docPackageTarget, out IPrintPreviewPageCollection docPageCollection) { Guid guid = new Guid(PreviewPackageIds.IID_PREVIEWPACKAGETARGET_DXGI); IntPtr target; docPackageTarget.GetPackageTarget(guid, guid, out target); this.dxgiPreviewTarget = (IPrintPreviewDxgiPackageTarget)Marshal.GetObjectForIUnknown(target); docPageCollection = (IPrintPreviewPageCollection)this; } public void MakeDocument(object printTaskOptions, IPrintDocumentPackageTarget docPackageTarget) { PrintTaskOptions options = (PrintTaskOptions)printTaskOptions; PrintPageDescription pagedesc = options.GetPageDescription(1); D2DPrintRender render = this.factory.CreateRender(pagedesc, docPackageTarget); PrintableView view = this.factory.CreateView(pagedesc, render, this.Header, this.Fotter); bool result = false; int currentPage = 0; while (!result) { if(!string.IsNullOrEmpty(this.Header)) view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Header)); if (!string.IsNullOrEmpty(this.Fotter)) view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Fotter)); render.DrawContent(view); result = view.TryPageDown(); currentPage++; } render.Dispose(); view.Dispose(); } public void Paginate(uint currentJobPage, object printTaskOptions) { PrintTaskOptions options = (PrintTaskOptions)printTaskOptions; PrintPageDescription pagedesc = options.GetPageDescription(currentJobPage); this.imageRect = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height); this.previewRender = this.factory.CreateRender(pagedesc); this.previewView = this.factory.CreateView(pagedesc, this.previewRender, this.Header, this.Fotter); int maxPage = 1; while (!this.previewView.TryPageDown()) maxPage++; this.dxgiPreviewTarget.SetJobPageCount(PageCountType.FinalPageCount, (uint)maxPage); this.dxgiPreviewTarget.InvalidatePreview(); this.maxPreviePageCount = maxPage; this.paginateCalled = true; } public void InvalidatePreview() { this.dxgiPreviewTarget.InvalidatePreview(); } public void MakePage(uint desiredJobPage, float width, float height) { if (width <= 0 || height <= 0) throw new COMException("", 0x70057/*E_INVALIDARG*/); if (!this.paginateCalled) return; if (desiredJobPage == 0xFFFFFFFF) desiredJobPage = 1; this.previewView.TryScroll(0, 0); //元に戻さないとページ番号が変わった時に正しく動作しない for (int i = 1; i < desiredJobPage; i++) this.previewView.TryPageDown(); if (!string.IsNullOrEmpty(this.Header)) this.previewView.Header = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Header)); if (!string.IsNullOrEmpty(this.Fotter)) this.previewView.Footer = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Fotter)); this.previewRender.Resize(width, height); this.previewRender.SetScale((float)(this.previewView.PageBound.Width / width)); //BeginDraw()で倍率が1に戻る this.previewRender.DrawContent(this.previewView, this.dxgiPreviewTarget, desiredJobPage); } public void Dispose() { if (this.previewView != null) this.previewView.Dispose(); if (this.previewRender != null) this.previewRender.Dispose(); } } }