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.
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.
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/>.
12 using System.Collections.Generic;
16 using System.Windows.Controls;
17 using System.Windows.Media;
18 using System.Windows.Input;
19 using System.Windows.Interop;
21 using DotNetTextStore;
22 using DotNetTextStore.UnmanagedAPI.TSF;
23 using DotNetTextStore.UnmanagedAPI.WinDef;
25 using D2D = SharpDX.Direct2D1;
26 using DW = SharpDX.DirectWrite;
27 using D3D11 = SharpDX.Direct3D11;
28 using D3D9 = SharpDX.Direct3D9;
29 using DXGI = SharpDX.DXGI;
31 namespace FooEditEngine.WPF
33 sealed class D2DRender : D2DRenderCommon, IEditorRender
35 DotNetTextStore.TextStore store;
36 D3D11.Texture2D texture;
40 D3D9.Surface surface9;
41 new D2D.RenderTarget render;
43 FontFamily fontFamily;
44 FontWeight fontWeigth;
48 public D2DRender(FooTextBox textbox, double width, double height,Image image)
50 this.fontFamily = textbox.FontFamily;
51 this.fontSize = textbox.FontSize;
52 this.fontWeigth = textbox.FontWeight;
53 this.fontStyle = textbox.FontStyle;
54 this.Foreground = ToColor4(textbox.Foreground);
55 this.Background = ToColor4(textbox.Background);
56 this.ControlChar = ToColor4(textbox.ControlChar);
57 this.Hilight = ToColor4(textbox.Hilight);
58 this.Comment = ToColor4(textbox.Comment);
59 this.Url = ToColor4(textbox.URL);
60 this.Keyword1 = ToColor4(textbox.Keyword1);
61 this.Keyword2 = ToColor4(textbox.Keyword2);
62 this.Literal = ToColor4(textbox.Literal);
63 this.InsertCaret = ToColor4(textbox.InsertCaret);
64 this.OverwriteCaret = ToColor4(textbox.OverwriteCaret);
65 this.LineMarker = ToColor4(textbox.LineMarker);
66 this.UpdateArea = ToColor4(textbox.UpdateArea);
67 this.LineNumber = ToColor4(textbox.LineNumber);
68 this.HilightForeground = ToColor4(textbox.HilightForeground);
69 this.store = textbox.TextStore;
73 this.ConstructDeviceResource(width, height);
74 this.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
76 this.imageSource = new D3DImage();
77 this.imageSource.Lock();
78 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer); //設定しないとロード時に例外が発生する
79 this.imageSource.Unlock();
81 image.Source = this.imageSource;
84 public FontFamily FontFamily
86 get { return this.fontFamily; }
89 this.fontFamily = value;
90 this.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
91 this.TabWidthChar = this.TabWidthChar;
95 public double FontSize
97 get { return this.fontSize; }
100 this.fontSize = value;
101 this.InitTextFormat(this.fontFamily.Source, (float)value, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
102 this.TabWidthChar = this.TabWidthChar;
106 public FontWeight FontWeigth
110 return this.fontWeigth;
114 this.fontWeigth = value;
115 this.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(value),this.GetDWFontStyle(this.fontStyle));
119 public FontStyle FontStyle
123 return this.fontStyle;
127 this.fontStyle = value;
128 this.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
132 public static Color4 ToColor4(System.Windows.Media.Color color)
134 return new Color4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f);
137 public bool Resize(double width, double height)
139 if (Math.Floor(width) != Math.Floor(this.imageSource.Width) || Math.Floor(height) != Math.Floor(this.imageSource.Height))
141 this.ReConstructDeviceResource(width, height);
142 this.imageSource.Lock();
143 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer);
144 this.imageSource.Unlock();
150 public void DrawContent(EditView view,bool IsEnabled,Rectangle updateRect)
152 if (this.imageSource.IsFrontBufferAvailable)
154 this.imageSource.Lock();
155 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer);
159 view.Draw(updateRect);
161 this.FillBackground(updateRect);
163 this.device.ImmediateContext.Flush();
165 this.imageSource.AddDirtyRect(new Int32Rect(0, 0, (int)this.imageSource.Width, (int)this.imageSource.Height));
166 this.imageSource.Unlock();
170 public void DrawOneLine(Document doc,LineToIndexTable lti, int row, double x, double y)
172 PreDrawOneLineHandler PreDrawOneLine = null;
174 if (InputMethod.Current.ImeState == InputMethodState.On)
175 PreDrawOneLine = this.DrawImeConversionLine;
177 base.DrawOneLine(doc,
186 private void DrawImeConversionLine(MyTextLayout layout,LineToIndexTable lti,int row,double x,double y)
188 using (Unlocker locker = this.store.LockDocument(false))
190 int lineIndex = lti.GetIndexFromLineNumber(row);
191 int lineLength = lti.GetLengthFromLineNumber(row);
192 foreach (TextDisplayAttribute attr in this.store.EnumAttributes(lineIndex, lineIndex + lineLength))
194 if (attr.startIndex == attr.endIndex)
196 int length = attr.endIndex - attr.startIndex;
197 int start = attr.startIndex - lineIndex;
199 HilightType type = HilightType.None;
200 Color4? color = null;
201 switch (attr.attribute.lsStyle)
203 case TF_DA_LINESTYLE.TF_LS_DOT:
204 type = HilightType.Dot;
205 color = this.GetColor4(attr.attribute.crLine);
207 case TF_DA_LINESTYLE.TF_LS_SOLID:
208 type = HilightType.Sold;
209 color = this.GetColor4(attr.attribute.crLine);
211 case TF_DA_LINESTYLE.TF_LS_DASH:
212 type = HilightType.Dash;
213 color = this.GetColor4(attr.attribute.crLine);
215 case TF_DA_LINESTYLE.TF_LS_SQUIGGLE:
216 type = HilightType.Squiggle;
217 color = this.GetColor4(attr.attribute.crLine);
221 if (attr.attribute.crBk.type != TF_DA_COLORTYPE.TF_CT_NONE)
223 type = HilightType.Select;
224 color = this.GetColor4(attr.attribute.crBk);
227 this.DrawMarkerEffect(layout, type, start, length, x, y, attr.attribute.fBoldLine, color);
229 color = this.GetColor4(attr.attribute.crText);
232 this.SetTextColor(layout, start, length, color);
233 layout.Invaild = true;
240 private Color4? GetColor4(TF_DA_COLOR cr)
245 case TF_DA_COLORTYPE.TF_CT_SYSCOLOR:
246 colorref = new COLORREF(NativeMethods.GetSysColor((int)cr.indexOrColorRef));
248 case TF_DA_COLORTYPE.TF_CT_COLORREF:
249 colorref = new COLORREF(cr.indexOrColorRef);
254 return new Color4(colorref.R / 255.0f, colorref.G / 255.0f, colorref.B / 255.0f, 1);
257 public override void Dispose()
260 this.DestructDevice();
263 DW.FontStyle GetDWFontStyle(FontStyle style)
265 return (DW.FontStyle)Enum.Parse(typeof(DW.FontStyle), style.ToString());
268 DW.FontWeight GetDWFontWeigth(FontWeight weigth)
270 return (DW.FontWeight)Enum.Parse(typeof(DW.FontWeight), weigth.ToString());
273 public override void DrawCachedBitmap(Rectangle rect)
275 if (this.render == null || this.render.IsDisposed)
277 render.DrawBitmap(this.cachedBitMap, rect, 1.0f, D2D.BitmapInterpolationMode.Linear, rect);
280 public override void CacheContent()
282 if (this.render == null || this.cachedBitMap == null || this.cachedBitMap.IsDisposed || this.render.IsDisposed)
285 this.cachedBitMap.CopyFromRenderTarget(this.render, new SharpDX.Point(), new SharpDX.Rectangle(0, 0, (int)this.renderSize.Width, (int)this.renderSize.Height));
286 this.hasCache = true;
291 SharpDX.Direct3D.FeatureLevel[] levels = new SharpDX.Direct3D.FeatureLevel[]{
292 SharpDX.Direct3D.FeatureLevel.Level_11_0,
293 SharpDX.Direct3D.FeatureLevel.Level_10_1,
294 SharpDX.Direct3D.FeatureLevel.Level_10_0,
295 SharpDX.Direct3D.FeatureLevel.Level_9_3,
296 SharpDX.Direct3D.FeatureLevel.Level_9_2,
297 SharpDX.Direct3D.FeatureLevel.Level_9_1};
298 foreach (var level in levels)
302 this.device = new D3D11.Device(SharpDX.Direct3D.DriverType.Hardware, D3D11.DeviceCreationFlags.BgraSupport, level);
310 if (this.device == null)
311 throw new PlatformNotSupportedException("DirectX10デバイスの作成に失敗しました");
313 IntPtr DesktopWnd = NativeMethods.GetDesktopWindow();
314 D3D9.Direct3DEx d3dex = new D3D9.Direct3DEx();
316 D3D9.PresentParameters param = new D3D9.PresentParameters();
317 param.Windowed = true;
318 param.SwapEffect = D3D9.SwapEffect.Discard;
319 param.DeviceWindowHandle = DesktopWnd;
320 param.PresentationInterval = D3D9.PresentInterval.Default;
324 this.device9 = new D3D9.DeviceEx(
327 D3D9.DeviceType.Hardware,
329 D3D9.CreateFlags.HardwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,
336 this.device9 = new D3D9.DeviceEx(
339 D3D9.DeviceType.Hardware,
341 D3D9.CreateFlags.SoftwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,
346 throw new PlatformNotSupportedException("DirectX9デバイスの作成に失敗しました");
355 void DestructDevice()
357 if (this.device != null)
359 this.device.Dispose();
362 if (this.device9 != null)
364 this.device9.Dispose();
369 protected override void ReCreateTarget()
371 System.Diagnostics.Debug.WriteLine("ReCreatedDevice");
372 this.DestructDevice();
374 this.ReConstructDeviceResource();
377 protected override D2D.RenderTarget ConstructRender(D2D.Factory factory, D2D.RenderTargetProperties prop, double width, double height)
379 D3D11.Texture2DDescription desc = new D3D11.Texture2DDescription();
380 desc.Width = (int)width;
381 desc.Height = (int)height;
384 desc.Format = DXGI.Format.B8G8R8A8_UNorm;
385 desc.SampleDescription = new DXGI.SampleDescription(1, 0);
386 desc.Usage = D3D11.ResourceUsage.Default;
387 desc.BindFlags = D3D11.BindFlags.RenderTarget | D3D11.BindFlags.ShaderResource;
388 desc.CpuAccessFlags = D3D11.CpuAccessFlags.None;
389 desc.OptionFlags = D3D11.ResourceOptionFlags.Shared;
390 this.texture = new D3D11.Texture2D(this.device, desc);
392 this.surface = this.texture.QueryInterface<DXGI.Surface>();
394 DXGI.Resource resource = this.texture.QueryInterface<DXGI.Resource>();
395 IntPtr handel = resource.SharedHandle;
396 D3D9.Texture texture = new D3D9.Texture(
398 this.texture.Description.Width,
399 this.texture.Description.Height,
401 D3D9.Usage.RenderTarget,
402 D3D9.Format.A8R8G8B8,
405 this.surface9 = texture.GetSurfaceLevel(0);
409 this.render = new D2D.RenderTarget(factory, this.surface, prop);
413 protected override void ConstrctedResource()
417 public double GetScale()
420 this.GetDpi(out dpi, out dpi);
424 public override void GetDpi(out float dpix, out float dpiy)
426 var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
427 var dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
429 dpix = (int)dpiXProperty.GetValue(null, null);
430 dpiy = (int)dpiYProperty.GetValue(null, null);
433 protected override void DestructRender()
435 if (this.texture != null)
436 this.texture.Dispose();
437 if (this.surface != null)
438 this.surface.Dispose();
439 if (this.surface9 != null)
440 this.surface9.Dispose();
441 if (this.render != null)
442 this.render.Dispose();