OSDN Git Service

行を生成するメソッドをLineToIndexTableに移動した
[fooeditengine/FooEditEngine.git] / Metro / FooEditEngine / Print / DocumentSource.cs
1 /*
2  * Copyright (C) 2013 FooProject
3  * * 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
4  * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
5
6  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
10  */
11 using System;
12 using Windows.Graphics.Display;
13 using Windows.Graphics.Printing;
14 using System.Runtime.InteropServices;
15 using Windows.UI;
16 using FooEditEngine.Metro;
17
18 namespace FooEditEngine
19 {
20     /// <summary>
21     /// イベントデータ
22     /// </summary>
23     public sealed class ParseCommandEventArgs
24     {
25         /// <summary>
26         /// 印刷中のページ番号
27         /// </summary>
28         public int PageNumber;
29         /// <summary>
30         /// ページ範囲内で許容されている最大の番号
31         /// </summary>
32         public int MaxPageNumber;
33         /// <summary>
34         /// 処理前の文字列
35         /// </summary>
36         public string Original;
37         /// <summary>
38         /// コンストラクター
39         /// </summary>
40         /// <param name="nowPage">印刷中のページ番号</param>
41         /// <param name="maxPage">印刷すべき最大のページ番号</param>
42         /// <param name="org">処理前の文字列</param>
43         public ParseCommandEventArgs(int nowPage, int maxPage, string org)
44         {
45             this.PageNumber = nowPage;
46             this.MaxPageNumber = maxPage;
47             this.Original = org;
48         }
49     }
50
51     /// <summary>
52     /// コマンド処理用デリゲート
53     /// </summary>
54     /// <param name="sender">送信元のクラス</param>
55     /// <param name="e">イベントデータ</param>
56     /// <returns>処理後の文字列</returns>
57     public delegate string ParseCommandHandler(object sender, ParseCommandEventArgs e);
58
59
60     sealed class PrintableViewFactory
61     {
62         Windows.UI.Color foreground, comment, keyword1, keyword2, literal, url;
63         string fontName;
64         double fontSize;
65         LineBreakMethod lineBreakMethod;
66         int lineBreakCharCount, tabCount;
67         Document document;
68         bool urlMark;
69         IHilighter hilighter;
70         float displayDpi;
71         Padding padding;
72         public PrintableViewFactory(FooTextBox textbox,Padding padding)
73         {
74             this.foreground = textbox.Foreground;
75             this.comment = textbox.Comment;
76             this.keyword1 = textbox.Keyword1;
77             this.keyword2 = textbox.Keyword2;
78             this.literal = textbox.Literal;
79             this.url = textbox.URL;
80             this.fontName = textbox.FontFamily.Source;
81             this.fontSize = textbox.FontSize;
82             this.tabCount = textbox.TabChars;
83             this.document = textbox.Document;
84             this.lineBreakMethod = textbox.LineBreakMethod;
85             this.lineBreakCharCount = textbox.LineBreakCharCount;
86             this.drawLineNumber = textbox.DrawLineNumber;
87             this.urlMark = textbox.MarkURL;
88             this.hilighter = textbox.Hilighter;
89             this.displayDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
90             this.padding = padding;
91             this.EnableHilight = true;
92         }
93         public D2DPrintRender CreateRender(PrintPageDescription pagedesc, IPrintDocumentPackageTarget docPackageTarget)
94         {
95             D2DPrintRender render;
96             Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
97             render = new D2DPrintRender(this.fontName, this.fontSize, size, Math.Min(pagedesc.DpiX, pagedesc.DpiY), docPackageTarget);
98             render.Foreground = D2DRenderBase.ToColor4(this.foreground);
99             render.Comment = D2DRenderBase.ToColor4(this.comment);
100             render.Keyword1 = D2DRenderBase.ToColor4(this.keyword1);
101             render.Keyword2 = D2DRenderBase.ToColor4(this.keyword2);
102             render.Literal = D2DRenderBase.ToColor4(this.literal);
103             render.Url = D2DRenderBase.ToColor4(this.url);
104             return render;
105         }
106         public D2DPrintPreviewRender CreateRender(PrintPageDescription pagedesc)
107         {
108             D2DPrintPreviewRender render;
109             Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
110             render = new D2DPrintPreviewRender(this.fontName, this.fontSize, size, this.displayDpi);
111             render.Foreground = D2DRenderBase.ToColor4(this.foreground);
112             render.Comment = D2DRenderBase.ToColor4(this.comment);
113             render.Keyword1 = D2DRenderBase.ToColor4(this.keyword1);
114             render.Keyword2 = D2DRenderBase.ToColor4(this.keyword2);
115             render.Literal = D2DRenderBase.ToColor4(this.literal);
116             render.Url = D2DRenderBase.ToColor4(this.url);
117             return render;
118         }
119         public PrintableView CreateView(PrintPageDescription pagedesc, IPrintableTextRender render, string header, string footer)
120         {
121             Document documentSnap = new Document(this.document);
122             documentSnap.LayoutLines.Render = render;
123             PrintableView view = new PrintableView(documentSnap, render,padding);
124             view.Header = header;
125             view.Footer = footer;
126             view.PageBound = new Rectangle(pagedesc.ImageableRect.X, pagedesc.ImageableRect.Y, pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
127             view.Hilighter = this.EnableHilight ? this.hilighter : null;
128             documentSnap.DrawLineNumber = this.drawLineNumber;
129             view.PerfomLayouts();
130
131             return view;
132         }
133
134         public bool drawLineNumber
135         {
136             get;
137             set;
138         }
139
140         public bool EnableHilight
141         {
142             get;
143             set;
144         }
145     }
146
147     sealed class DocumentSource : IPrintDocumentPageSource, IPrintPreviewPageCollection, IPrintDocumentSource,IPrintPreviewSource
148     {
149         IPrintPreviewDxgiPackageTarget dxgiPreviewTarget;
150         bool paginateCalled = false;
151         Size imageRect;
152         PrintableViewFactory factory;
153         D2DPrintPreviewRender previewRender;
154         PrintableView previewView;
155         int maxPreviePageCount;
156
157         public ParseCommandHandler ParseHF;
158         public string Header = string.Empty;
159         public string Fotter = string.Empty;
160
161         public DocumentSource(FooTextBox textbox,Padding padding)
162         {
163             this.factory = new PrintableViewFactory(textbox, padding);
164         }
165
166         internal enum SyntaxHilightApplibility
167         {
168             Apply,
169             NoApply,
170         }
171
172         [DisplayPrintOptionResourceID("SyntaxHilight")]
173         internal SyntaxHilightApplibility EnableHilight
174         {
175             get
176             {
177                 return this.factory.EnableHilight ? SyntaxHilightApplibility.Apply : SyntaxHilightApplibility.NoApply;
178             }
179             set
180             {
181                 this.factory.EnableHilight = value == SyntaxHilightApplibility.Apply;
182             }
183         }
184
185         internal enum LineNumberVisiblity
186         {
187             Visible,
188             Hidden
189         }
190
191         [DisplayPrintOptionResourceID("ShowLineNumber")]
192         internal LineNumberVisiblity ShowLineNumber
193         {
194             get
195             {
196                 return this.factory.drawLineNumber ? LineNumberVisiblity.Visible : LineNumberVisiblity.Hidden;
197             }
198             set
199             {
200                 this.factory.drawLineNumber = value == LineNumberVisiblity.Visible;
201             }
202         }
203
204         public void GetPreviewPageCollection(IPrintDocumentPackageTarget docPackageTarget, out IPrintPreviewPageCollection docPageCollection)
205         {
206             Guid guid = new Guid(PreviewPackageIds.IID_PREVIEWPACKAGETARGET_DXGI);
207             IntPtr target;
208             docPackageTarget.GetPackageTarget(guid, guid, out target);
209             this.dxgiPreviewTarget = (IPrintPreviewDxgiPackageTarget)Marshal.GetObjectForIUnknown(target);
210             docPageCollection = (IPrintPreviewPageCollection)this;
211         }
212
213         public void MakeDocument(object printTaskOptions, IPrintDocumentPackageTarget docPackageTarget)
214         {
215             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;
216             PrintPageDescription pagedesc = options.GetPageDescription(1);
217
218             D2DPrintRender render = this.factory.CreateRender(pagedesc, docPackageTarget);
219             PrintableView view = this.factory.CreateView(pagedesc, render, this.Header, this.Fotter);
220
221             bool result = false;
222             int currentPage = 0;
223
224             while (!result)
225             {
226                 if(!string.IsNullOrEmpty(this.Header))
227                     view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Header));
228                 if (!string.IsNullOrEmpty(this.Fotter))
229                     view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Fotter));
230
231                 render.DrawContent(view);
232
233                 result = view.TryPageDown();
234                 currentPage++;
235             }
236
237             render.Dispose();
238             view.Dispose();
239         }
240
241         public void Paginate(uint currentJobPage, object printTaskOptions)
242         {
243             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;
244             PrintPageDescription pagedesc = options.GetPageDescription(currentJobPage);
245
246             this.imageRect = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);
247
248             this.previewRender = this.factory.CreateRender(pagedesc);
249             this.previewView = this.factory.CreateView(pagedesc, this.previewRender, this.Header, this.Fotter);
250
251             int maxPage = 1;
252             while (!this.previewView.TryPageDown())
253                 maxPage++;
254
255             this.dxgiPreviewTarget.SetJobPageCount(PageCountType.FinalPageCount, (uint)maxPage);
256
257             this.dxgiPreviewTarget.InvalidatePreview();
258
259             this.maxPreviePageCount = maxPage;
260
261             this.paginateCalled = true;
262         }
263
264         public void InvalidatePreview()
265         {
266             this.dxgiPreviewTarget.InvalidatePreview();
267         }
268
269         public void MakePage(uint desiredJobPage, float width, float height)
270         {
271             if (width <= 0 || height <= 0)
272                 throw new COMException("", 0x70057/*E_INVALIDARG*/);
273             if (!this.paginateCalled)
274                 return;
275             if (desiredJobPage == 0xFFFFFFFF)
276                 desiredJobPage = 1;
277
278             this.previewView.TryScroll(0, 0);   //元に戻さないとページ番号が変わった時に正しく動作しない
279
280             for (int i = 1; i < desiredJobPage; i++)
281                 this.previewView.TryPageDown();
282
283             if (!string.IsNullOrEmpty(this.Header))
284                 this.previewView.Header = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Header));
285             if (!string.IsNullOrEmpty(this.Fotter))
286                 this.previewView.Footer = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Fotter));
287
288             this.previewRender.Resize(width, height);
289             this.previewRender.SetScale((float)(this.previewView.PageBound.Width / width)); //BeginDraw()で倍率が1に戻る
290
291             this.previewRender.DrawContent(this.previewView, this.dxgiPreviewTarget, desiredJobPage);
292         }
293
294         public void Dispose()
295         {
296             if (this.previewView != null)
297                 this.previewView.Dispose();
298             if (this.previewRender != null)
299                 this.previewRender.Dispose();
300         }
301     }
302 }