OSDN Git Service

D2DRenderCommonをそれぞれのレンダーで継承するようにした
[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         Document document;\r
66         LineBreakMethod lineBreakMethod;\r
67         int lineBreakCharCount, tabCount;\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 = new 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 D2DRenderBase CreateRender(PrintPageDescription pagedesc, IPrintDocumentPackageTarget docPackageTarget)\r
94         {\r
95             D2DRenderBase 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, D2DRenderBase render, string header, string footer)\r
120         {\r
121             PrintableView view = new PrintableView(this.document, (IPrintableTextRender)render,padding);\r
122             view.TabStops = this.tabCount;\r
123             view.LineBreak = this.lineBreakMethod == LineBreakMethod.None ? LineBreakMethod.PageBound : this.lineBreakMethod;\r
124             view.LineBreakCharCount = this.lineBreakCharCount;\r
125             view.DrawLineNumber = this.drawLineNumber;\r
126             view.Header = header;\r
127             view.Footer = footer;\r
128             view.UrlMark = this.urlMark;\r
129             view.PageBound = new Rectangle(pagedesc.ImageableRect.X, pagedesc.ImageableRect.Y, pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
130             view.Hilighter = this.EnableHilight ? this.hilighter : null;\r
131             view.PerfomLayouts();\r
132 \r
133             return view;\r
134         }\r
135 \r
136         public bool drawLineNumber\r
137         {\r
138             get;\r
139             set;\r
140         }\r
141 \r
142         public bool EnableHilight\r
143         {\r
144             get;\r
145             set;\r
146         }\r
147     }\r
148 \r
149     sealed class DocumentSource : IPrintDocumentPageSource, IPrintPreviewPageCollection, IPrintDocumentSource,IPrintPreviewSource\r
150     {\r
151         IPrintPreviewDxgiPackageTarget dxgiPreviewTarget;\r
152         bool paginateCalled = false;\r
153         Size imageRect;\r
154         PrintableViewFactory factory;\r
155         D2DPrintPreviewRender previewRender;\r
156         PrintableView previewView;\r
157         int maxPreviePageCount;\r
158 \r
159         public ParseCommandHandler ParseHF;\r
160         public string Header = string.Empty;\r
161         public string Fotter = string.Empty;\r
162 \r
163         public DocumentSource(FooTextBox textbox,Padding padding)\r
164         {\r
165             this.factory = new PrintableViewFactory(textbox, padding);\r
166         }\r
167 \r
168         internal enum SyntaxHilightApplibility\r
169         {\r
170             Apply,\r
171             NoApply,\r
172         }\r
173 \r
174         [DisplayPrintOptionResourceID("SyntaxHilight")]\r
175         internal SyntaxHilightApplibility EnableHilight\r
176         {\r
177             get\r
178             {\r
179                 return this.factory.EnableHilight ? SyntaxHilightApplibility.Apply : SyntaxHilightApplibility.NoApply;\r
180             }\r
181             set\r
182             {\r
183                 this.factory.EnableHilight = value == SyntaxHilightApplibility.Apply;\r
184             }\r
185         }\r
186 \r
187         internal enum LineNumberVisiblity\r
188         {\r
189             Visible,\r
190             Hidden\r
191         }\r
192 \r
193         [DisplayPrintOptionResourceID("ShowLineNumber")]\r
194         internal LineNumberVisiblity ShowLineNumber\r
195         {\r
196             get\r
197             {\r
198                 return this.factory.drawLineNumber ? LineNumberVisiblity.Visible : LineNumberVisiblity.Hidden;\r
199             }\r
200             set\r
201             {\r
202                 this.factory.drawLineNumber = value == LineNumberVisiblity.Visible;\r
203             }\r
204         }\r
205 \r
206         public void GetPreviewPageCollection(IPrintDocumentPackageTarget docPackageTarget, out IPrintPreviewPageCollection docPageCollection)\r
207         {\r
208             Guid guid = new Guid(PreviewPackageIds.IID_PREVIEWPACKAGETARGET_DXGI);\r
209             IntPtr target;\r
210             docPackageTarget.GetPackageTarget(guid, guid, out target);\r
211             this.dxgiPreviewTarget = (IPrintPreviewDxgiPackageTarget)Marshal.GetObjectForIUnknown(target);\r
212             docPageCollection = (IPrintPreviewPageCollection)this;\r
213         }\r
214 \r
215         public void MakeDocument(object printTaskOptions, IPrintDocumentPackageTarget docPackageTarget)\r
216         {\r
217             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;\r
218             PrintPageDescription pagedesc = options.GetPageDescription(1);\r
219 \r
220             D2DRenderBase render = this.factory.CreateRender(pagedesc, docPackageTarget);\r
221             PrintableView view = this.factory.CreateView(pagedesc, render, this.Header, this.Fotter);\r
222 \r
223             bool result = false;\r
224             int currentPage = 0;\r
225 \r
226             while (!result)\r
227             {\r
228                 if(!string.IsNullOrEmpty(this.Header))\r
229                     view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Header));\r
230                 if (!string.IsNullOrEmpty(this.Fotter))\r
231                     view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, this.maxPreviePageCount, this.Fotter));\r
232 \r
233                 render.BegineDraw();\r
234                 view.Draw(view.PageBound);\r
235                 render.EndDraw();\r
236                 result = view.TryPageDown();\r
237                 currentPage++;\r
238             }\r
239 \r
240             render.Dispose();\r
241             view.Dispose();\r
242         }\r
243 \r
244         public void Paginate(uint currentJobPage, object printTaskOptions)\r
245         {\r
246             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;\r
247             PrintPageDescription pagedesc = options.GetPageDescription(currentJobPage);\r
248 \r
249             this.imageRect = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
250 \r
251             this.previewRender = this.factory.CreateRender(pagedesc);\r
252             this.previewView = this.factory.CreateView(pagedesc, this.previewRender, this.Header, this.Fotter);\r
253 \r
254             int maxPage = 1;\r
255             while (!this.previewView.TryPageDown())\r
256                 maxPage++;\r
257 \r
258             this.dxgiPreviewTarget.SetJobPageCount(PageCountType.FinalPageCount, (uint)maxPage);\r
259 \r
260             this.dxgiPreviewTarget.InvalidatePreview();\r
261 \r
262             this.maxPreviePageCount = maxPage;\r
263 \r
264             this.paginateCalled = true;\r
265         }\r
266 \r
267         public void InvalidatePreview()\r
268         {\r
269             this.dxgiPreviewTarget.InvalidatePreview();\r
270         }\r
271 \r
272         public void MakePage(uint desiredJobPage, float width, float height)\r
273         {\r
274             if (width <= 0 || height <= 0)\r
275                 throw new COMException("", 0x70057/*E_INVALIDARG*/);\r
276             if (!this.paginateCalled)\r
277                 return;\r
278             if (desiredJobPage == 0xFFFFFFFF)\r
279                 desiredJobPage = 1;\r
280 \r
281             this.previewView.TryScroll(0, 0);   //元に戻さないとページ番号が変わった時に正しく動作しない\r
282 \r
283             for (int i = 1; i < desiredJobPage; i++)\r
284                 this.previewView.TryPageDown();\r
285 \r
286             if (!string.IsNullOrEmpty(this.Header))\r
287                 this.previewView.Header = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Header));\r
288             if (!string.IsNullOrEmpty(this.Fotter))\r
289                 this.previewView.Footer = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Fotter));\r
290 \r
291             this.previewRender.Resize(width, height);\r
292             this.previewRender.SetScale((float)(this.previewView.PageBound.Width / width)); //BeginDraw()で倍率が1に戻る\r
293 \r
294             this.previewRender.BegineDraw();\r
295             this.previewView.Draw(this.previewView.PageBound);\r
296             this.previewRender.EndDraw(this.dxgiPreviewTarget,desiredJobPage);\r
297         }\r
298 \r
299         public void Dispose()\r
300         {\r
301             if (this.previewView != null)\r
302                 this.previewView.Dispose();\r
303             if (this.previewRender != null)\r
304                 this.previewRender.Dispose();\r
305         }\r
306     }\r
307 }\r