OSDN Git Service

一部パラメーターが正常に処理されないバグを修正した
[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     sealed class PrintableViewFactory\r
60     {\r
61         Windows.UI.Color foreground, comment, keyword1, keyword2, literal, url;\r
62         string fontName;\r
63         double fontSize;\r
64         Document document;\r
65         LineBreakMethod lineBreakMethod;\r
66         int lineBreakCharCount, tabCount;\r
67         bool drawLineNumber, urlMark;\r
68         IHilighter hilighter;\r
69         float displayDpi;\r
70         public PrintableViewFactory(FooTextBox textbox)\r
71         {\r
72             this.foreground = textbox.Foreground;\r
73             this.comment = textbox.Comment;\r
74             this.keyword1 = textbox.Keyword1;\r
75             this.keyword2 = textbox.Keyword2;\r
76             this.literal = textbox.Literal;\r
77             this.url = textbox.URL;\r
78             this.fontName = textbox.FontFamily.Source;\r
79             this.fontSize = textbox.FontSize;\r
80             this.tabCount = textbox.TabChars;\r
81             this.document = new Document(textbox.Document);\r
82             this.lineBreakMethod = textbox.LineBreakMethod;\r
83             this.lineBreakCharCount = textbox.LineBreakCharCount;\r
84             this.drawLineNumber = textbox.DrawLineNumber;\r
85             this.urlMark = textbox.MarkURL;\r
86             this.hilighter = textbox.Hilighter;\r
87             this.displayDpi = DisplayInformation.GetForCurrentView().LogicalDpi;\r
88         }\r
89         public D2DRenderBase CreateRender(PrintPageDescription pagedesc, IPrintDocumentPackageTarget docPackageTarget)\r
90         {\r
91             D2DRenderBase render;\r
92             Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
93             render = new D2DPrintRender(this.fontName, this.fontSize, size, Math.Min(pagedesc.DpiX, pagedesc.DpiY), docPackageTarget);\r
94             render.Foreground = this.foreground;\r
95             render.Comment = this.comment;\r
96             render.Keyword1 = this.keyword1;\r
97             render.Keyword2 = this.keyword2;\r
98             render.Literal = this.literal;\r
99             render.Url = this.url;\r
100             return render;\r
101         }\r
102         public D2DPrintPreviewRender CreateRender(PrintPageDescription pagedesc)\r
103         {\r
104             D2DPrintPreviewRender render;\r
105             Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
106             render = new D2DPrintPreviewRender(this.fontName, this.fontSize, size, this.displayDpi);\r
107             render.Foreground = this.foreground;\r
108             render.Comment = this.comment;\r
109             render.Keyword1 = this.keyword1;\r
110             render.Keyword2 = this.keyword2;\r
111             render.Literal = this.literal;\r
112             render.Url = this.url;\r
113             return render;\r
114         }\r
115         public PrintableView CreateView(PrintPageDescription pagedesc, D2DRenderBase render, string header, string footer)\r
116         {\r
117             PrintableView view = new PrintableView(this.document, (IPrintableTextRender)render);\r
118             view.TabStops = this.tabCount;\r
119             view.LineBreak = this.lineBreakMethod == LineBreakMethod.None ? LineBreakMethod.PageBound : this.lineBreakMethod;\r
120             view.LineBreakCharCount = this.lineBreakCharCount;\r
121             view.DrawLineNumber = this.drawLineNumber;\r
122             view.Header = header;\r
123             view.Footer = footer;\r
124             view.UrlMark = this.urlMark;\r
125             view.PageBound = new Rectangle(pagedesc.ImageableRect.X, pagedesc.ImageableRect.Y, pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
126             view.Hilighter = this.hilighter;\r
127             view.PerfomLayouts();\r
128 \r
129             return view;\r
130         }\r
131     }\r
132 \r
133     sealed class DocumentSource : IPrintDocumentPageSource, IPrintPreviewPageCollection, IPrintDocumentSource\r
134     {\r
135         IPrintPreviewDxgiPackageTarget dxgiPreviewTarget;\r
136         bool paginateCalled = false;\r
137         Size imageRect;\r
138         PrintableViewFactory factory;\r
139         D2DPrintPreviewRender previewRender;\r
140         PrintableView previewView;\r
141         int maxPreviePageCount;\r
142 \r
143         public ParseCommandHandler ParseHF;\r
144         public string Header = string.Empty;\r
145         public string Fotter = string.Empty;\r
146 \r
147         public DocumentSource(FooTextBox textbox)\r
148         {\r
149             this.factory = new PrintableViewFactory(textbox);\r
150         }\r
151 \r
152         public void GetPreviewPageCollection(IPrintDocumentPackageTarget docPackageTarget,out IPrintPreviewPageCollection docPageCollection)\r
153         {\r
154             Guid guid = new Guid(PreviewPackageIds.IID_PREVIEWPACKAGETARGET_DXGI);\r
155             IntPtr target;\r
156             docPackageTarget.GetPackageTarget(guid, guid, out target);\r
157             this.dxgiPreviewTarget = (IPrintPreviewDxgiPackageTarget)Marshal.GetObjectForIUnknown(target);\r
158             docPageCollection = (IPrintPreviewPageCollection)this;\r
159         }\r
160 \r
161         public void MakeDocument(object printTaskOptions, IPrintDocumentPackageTarget docPackageTarget)\r
162         {\r
163             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;\r
164             PrintPageDescription pagedesc = options.GetPageDescription(1);\r
165 \r
166             D2DRenderBase render = this.factory.CreateRender(pagedesc, docPackageTarget);\r
167             PrintableView view = this.factory.CreateView(pagedesc, render, this.Header, this.Fotter);\r
168 \r
169             bool result = false;\r
170             int currentPage = 0;\r
171 \r
172             while (!result)\r
173             {\r
174                 if(!string.IsNullOrEmpty(this.Header))\r
175                     view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, -1, this.Header));\r
176                 if (!string.IsNullOrEmpty(this.Fotter))\r
177                     view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, -1, this.Fotter));\r
178 \r
179                 render.BeginDraw();\r
180                 view.Draw(view.PageBound);\r
181                 render.EndDraw();\r
182                 result = view.TryPageDown();\r
183                 currentPage++;\r
184             }\r
185 \r
186             render.Dispose();\r
187             view.Dispose();\r
188         }\r
189 \r
190         public void Paginate(uint currentJobPage, object printTaskOptions)\r
191         {\r
192             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;\r
193             PrintPageDescription pagedesc = options.GetPageDescription(currentJobPage);\r
194 \r
195             this.imageRect = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
196 \r
197             this.previewRender = this.factory.CreateRender(pagedesc);\r
198             this.previewView = this.factory.CreateView(pagedesc, this.previewRender, this.Header, this.Fotter);\r
199 \r
200             int maxPage = 1;\r
201             while (!this.previewView.TryPageDown())\r
202                 maxPage++;\r
203 \r
204             this.dxgiPreviewTarget.SetJobPageCount(PageCountType.FinalPageCount, (uint)maxPage);\r
205 \r
206             this.dxgiPreviewTarget.InvalidatePreview();\r
207 \r
208             this.maxPreviePageCount = maxPage;\r
209 \r
210             this.paginateCalled = true;\r
211         }\r
212 \r
213         public void MakePage(uint desiredJobPage, float width, float height)\r
214         {\r
215             if (width <= 0 || height <= 0)\r
216                 throw new COMException("", 0x70057/*E_INVALIDARG*/);\r
217             if (!this.paginateCalled)\r
218                 return;\r
219             if (desiredJobPage == 0xFFFFFFFF)\r
220                 desiredJobPage = 1;\r
221 \r
222             this.previewView.TryScroll(0, 0);   //元に戻さないとページ番号が変わった時に正しく動作しない\r
223 \r
224             for (int i = 1; i < desiredJobPage; i++)\r
225                 this.previewView.TryPageDown();\r
226 \r
227             if (!string.IsNullOrEmpty(this.Header))\r
228                 this.previewView.Header = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Header));\r
229             if (!string.IsNullOrEmpty(this.Fotter))\r
230                 this.previewView.Footer = this.ParseHF(this, new ParseCommandEventArgs((int)desiredJobPage, this.maxPreviePageCount, this.Fotter));\r
231 \r
232             this.previewRender.Resize(width, height);\r
233             this.previewRender.SetScale((float)(this.previewView.PageBound.Width / width)); //BeginDraw()で倍率が1に戻る\r
234 \r
235             this.previewRender.BeginDraw();\r
236             this.previewView.Draw(this.previewView.PageBound);\r
237             this.previewRender.EndDraw(this.dxgiPreviewTarget,desiredJobPage);\r
238         }\r
239 \r
240         public void Dispose()\r
241         {\r
242             if (this.previewView != null)\r
243                 this.previewView.Dispose();\r
244             if (this.previewRender != null)\r
245                 this.previewRender.Dispose();\r
246         }\r
247     }\r
248 }\r