OSDN Git Service

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