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.Printing;\r
13 using System.Runtime.InteropServices;\r
14 using Windows.UI;\r
15 using FooEditEngine.Metro;\r
16 \r
17 namespace FooEditEngine\r
18 {\r
19     /// <summary>\r
20     /// イベントデータ\r
21     /// </summary>\r
22     public sealed class ParseCommandEventArgs\r
23     {\r
24         /// <summary>\r
25         /// 印刷中のページ番号\r
26         /// </summary>\r
27         public int PageNumber;\r
28         /// <summary>\r
29         /// ページ範囲内で許容されている最大の番号\r
30         /// </summary>\r
31         public int MaxPageNumber;\r
32         /// <summary>\r
33         /// 処理前の文字列\r
34         /// </summary>\r
35         public string Original;\r
36         /// <summary>\r
37         /// コンストラクター\r
38         /// </summary>\r
39         /// <param name="nowPage">印刷中のページ番号</param>\r
40         /// <param name="maxPage">印刷すべき最大のページ番号</param>\r
41         /// <param name="org">処理前の文字列</param>\r
42         public ParseCommandEventArgs(int nowPage, int maxPage, string org)\r
43         {\r
44             this.PageNumber = nowPage;\r
45             this.MaxPageNumber = maxPage;\r
46             this.Original = org;\r
47         }\r
48     }\r
49 \r
50     /// <summary>\r
51     /// コマンド処理用デリゲート\r
52     /// </summary>\r
53     /// <param name="sender">送信元のクラス</param>\r
54     /// <param name="e">イベントデータ</param>\r
55     /// <returns>処理後の文字列</returns>\r
56     public delegate string ParseCommandHandler(object sender, ParseCommandEventArgs e);\r
57 \r
58     sealed class PrintableViewFactory\r
59     {\r
60         Windows.UI.Color foreground, comment, keyword1, keyword2, literal, url;\r
61         string fontName;\r
62         double fontSize;\r
63         Document document;\r
64         LineBreakMethod lineBreakMethod;\r
65         int lineBreakCharCount, tabCount;\r
66         bool drawLineNumber, urlMark;\r
67         IHilighter hilighter;\r
68         public PrintableViewFactory(FooTextBox textbox)\r
69         {\r
70             this.foreground = textbox.Foreground;\r
71             this.comment = textbox.Comment;\r
72             this.keyword1 = textbox.Keyword1;\r
73             this.keyword2 = textbox.Keyword2;\r
74             this.literal = textbox.Literal;\r
75             this.url = textbox.URL;\r
76             this.fontName = textbox.FontFamily.Source;\r
77             this.fontSize = textbox.FontSize;\r
78             this.tabCount = textbox.TabChars;\r
79             this.document = new Document(textbox.Document);\r
80             this.lineBreakMethod = textbox.LineBreakMethod;\r
81             this.lineBreakCharCount = textbox.LineBreakCharCount;\r
82             this.drawLineNumber = textbox.DrawLineNumber;\r
83             this.urlMark = textbox.MarkURL;\r
84             this.hilighter = textbox.Hilighter;\r
85         }\r
86         public D2DRenderBase CreateRender(PrintPageDescription pagedesc, IPrintDocumentPackageTarget docPackageTarget)\r
87         {\r
88             D2DRenderBase render;\r
89             Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
90             render = new D2DPrintRender(this.fontName, this.fontSize, size, Math.Min(pagedesc.DpiX, pagedesc.DpiY), docPackageTarget);\r
91             render.Foreground = this.foreground;\r
92             render.Comment = this.comment;\r
93             render.Keyword1 = this.keyword1;\r
94             render.Keyword2 = this.keyword2;\r
95             render.Literal = this.literal;\r
96             render.Url = this.url;\r
97             return render;\r
98         }\r
99         public D2DPrintPreviewRender CreateRender(PrintPageDescription pagedesc)\r
100         {\r
101             D2DPrintPreviewRender render;\r
102             Size size = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
103             render = new D2DPrintPreviewRender(this.fontName, this.fontSize, size);\r
104             render.Foreground = this.foreground;\r
105             render.Comment = this.comment;\r
106             render.Keyword1 = this.keyword1;\r
107             render.Keyword2 = this.keyword2;\r
108             render.Literal = this.literal;\r
109             render.Url = this.url;\r
110             return render;\r
111         }\r
112         public PrintableView CreateView(PrintPageDescription pagedesc, D2DRenderBase render, string header, string footer)\r
113         {\r
114             PrintableView view = new PrintableView(this.document, (IPrintableTextRender)render);\r
115             view.TabStops = this.tabCount;\r
116             view.LineBreak = this.lineBreakMethod == LineBreakMethod.None ? LineBreakMethod.PageBound : this.lineBreakMethod;\r
117             view.LineBreakCharCount = this.lineBreakCharCount;\r
118             view.DrawLineNumber = this.drawLineNumber;\r
119             view.Header = header;\r
120             view.Footer = footer;\r
121             view.UrlMark = this.urlMark;\r
122             view.PageBound = new Rectangle(pagedesc.ImageableRect.X, pagedesc.ImageableRect.Y, pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
123             view.Hilighter = this.hilighter;\r
124             view.PerfomLayouts();\r
125 \r
126             return view;\r
127         }\r
128     }\r
129 \r
130     sealed class DocumentSource : IPrintDocumentPageSource, IPrintPreviewPageCollection, IPrintDocumentSource\r
131     {\r
132         IPrintPreviewDxgiPackageTarget dxgiPreviewTarget;\r
133         bool paginateCalled = false;\r
134         Size imageRect;\r
135         PrintableViewFactory factory;\r
136         D2DPrintPreviewRender previewRender;\r
137         PrintableView previewView;\r
138 \r
139         public ParseCommandHandler ParseHF;\r
140         public string Header = string.Empty;\r
141         public string Fotter = string.Empty;\r
142 \r
143         public DocumentSource(FooTextBox textbox)\r
144         {\r
145             this.factory = new PrintableViewFactory(textbox);\r
146             this.ParseHF = (s, e) => { return e.Original; };\r
147         }\r
148 \r
149         public void GetPreviewPageCollection(IPrintDocumentPackageTarget docPackageTarget,out IPrintPreviewPageCollection docPageCollection)\r
150         {\r
151             Guid guid = new Guid(PreviewPackageIds.IID_PREVIEWPACKAGETARGET_DXGI);\r
152             IntPtr target;\r
153             docPackageTarget.GetPackageTarget(guid, guid, out target);\r
154             this.dxgiPreviewTarget = (IPrintPreviewDxgiPackageTarget)Marshal.GetObjectForIUnknown(target);\r
155             docPageCollection = (IPrintPreviewPageCollection)this;\r
156         }\r
157 \r
158         public void MakeDocument(object printTaskOptions, IPrintDocumentPackageTarget docPackageTarget)\r
159         {\r
160             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;\r
161             PrintPageDescription pagedesc = options.GetPageDescription(1);\r
162 \r
163             D2DRenderBase render = this.factory.CreateRender(pagedesc, docPackageTarget);\r
164             PrintableView view = this.factory.CreateView(pagedesc, render, this.Header, this.Fotter);\r
165 \r
166             bool result = false;\r
167             int currentPage = 0;\r
168 \r
169             while (!result)\r
170             {\r
171                 if(!string.IsNullOrEmpty(this.Header))\r
172                     view.Header = this.ParseHF(this, new ParseCommandEventArgs(currentPage, -1, this.Header));\r
173                 if (!string.IsNullOrEmpty(this.Fotter))\r
174                     view.Footer = this.ParseHF(this, new ParseCommandEventArgs(currentPage, -1, this.Fotter));\r
175 \r
176                 render.BeginDraw();\r
177                 view.Draw(view.PageBound);\r
178                 render.EndDraw();\r
179                 result = view.TryPageDown();\r
180                 currentPage++;\r
181             }\r
182 \r
183             render.Dispose();\r
184             view.Dispose();\r
185         }\r
186 \r
187         public void Paginate(uint currentJobPage, object printTaskOptions)\r
188         {\r
189             PrintTaskOptions options = (PrintTaskOptions)printTaskOptions;\r
190             PrintPageDescription pagedesc = options.GetPageDescription(currentJobPage);\r
191 \r
192             this.imageRect = new Size(pagedesc.ImageableRect.Width, pagedesc.ImageableRect.Height);\r
193 \r
194             this.previewRender = this.factory.CreateRender(pagedesc);\r
195             this.previewView = this.factory.CreateView(pagedesc, this.previewRender, this.Header, this.Fotter);\r
196 \r
197             int maxPage = 1;\r
198             while (!this.previewView.TryPageDown())\r
199                 maxPage++;\r
200 \r
201             this.dxgiPreviewTarget.SetJobPageCount(PageCountType.FinalPageCount, (uint)maxPage);\r
202 \r
203             this.dxgiPreviewTarget.InvalidatePreview();\r
204 \r
205             this.paginateCalled = true;\r
206         }\r
207 \r
208         public void MakePage(uint desiredJobPage, float width, float height)\r
209         {\r
210             if (width <= 0 || height <= 0)\r
211                 throw new COMException("", 0x70057/*E_INVALIDARG*/);\r
212             if (!this.paginateCalled)\r
213                 return;\r
214             if (desiredJobPage == 0xFFFFFFFF)\r
215                 desiredJobPage = 1;\r
216 \r
217             this.previewView.TryScroll(0, 0);   //元に戻さないとページ番号が変わった時に正しく動作しない\r
218 \r
219             for (int i = 1; i < desiredJobPage; i++)\r
220                 this.previewView.TryPageDown();\r
221 \r
222             this.previewRender.Resize(width, height);\r
223             this.previewRender.SetScale((float)(this.previewView.PageBound.Width / width)); //BeginDraw()で倍率が1に戻る\r
224 \r
225             this.previewRender.BeginDraw();\r
226             this.previewView.Draw(this.previewView.PageBound);\r
227             this.previewRender.EndDraw(this.dxgiPreviewTarget,desiredJobPage);\r
228         }\r
229 \r
230         public void Dispose()\r
231         {\r
232             if (this.previewView != null)\r
233                 this.previewView.Dispose();\r
234             if (this.previewRender != null)\r
235                 this.previewRender.Dispose();\r
236         }\r
237     }\r
238 }\r