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.Interop;
20 using DotNetTextStore;
21 using DotNetTextStore.UnmanagedAPI.TSF;
22 using DotNetTextStore.UnmanagedAPI.WinDef;
24 using D2D = SharpDX.Direct2D1;
25 using DW = SharpDX.DirectWrite;
26 using D3D10 = SharpDX.Direct3D10;
27 using D3D9 = SharpDX.Direct3D9;
28 using DXGI = SharpDX.DXGI;
30 namespace FooEditEngine.WPF
32 class D2DRender : ITextRender, IDisposable
34 D2DRenderCommon common;
35 System.Windows.Media.Color ForegroundColor, BackgroundColor, HilightColor, Keyword1Color, Keyword2Color, LiteralColor, UrlColor, ControlCharColor, CommentColor, InsertCaretColor,OverwriteCaretColor,LineMarkerColor;
36 DotNetTextStore.TextStore store;
37 D3D10.Texture2D texture;
41 D3D9.Surface surface9;
42 D2D.RenderTarget render;
44 FontFamily fontFamily;
45 FontWeight fontWeigth;
49 public D2DRender(FooTextBox textbox, double width, double height,Image image)
51 this.fontFamily = textbox.FontFamily;
52 this.fontSize = textbox.FontSize;
53 this.fontWeigth = textbox.FontWeight;
54 this.fontStyle = textbox.FontStyle;
55 this.ForegroundColor = textbox.Foreground;
56 this.BackgroundColor = textbox.Background;
57 this.ControlCharColor = textbox.ControlChar;
58 this.HilightColor = textbox.Hilight;
59 this.CommentColor = textbox.Comment;
60 this.UrlColor = textbox.URL;
61 this.Keyword1Color = textbox.Keyword1;
62 this.Keyword2Color = textbox.Keyword2;
63 this.LiteralColor = textbox.Literal;
64 this.InsertCaretColor = textbox.InsertCaret;
65 this.OverwriteCaretColor = textbox.OverwriteCaret;
66 this.LineMarkerColor = textbox.LineMarker;
67 this.store = textbox.TextStore;
71 this.common = new D2DRenderCommon();
72 this.common.ConstructRender = ConstructRenderHandler;
73 this.common.ConstrctedResource = ConstructedResourceHandler;
74 this.common.DestructRender = this.DestructRenderHandler;
75 this.common.ReCreateTarget = this.ReCreateTarget;
76 this.common.GetDpi = this.GetDpi;
77 this.common.ConstructDeviceResource(width, height);
78 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
80 this.imageSource = new D3DImage();
81 this.imageSource.Lock();
82 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer); //設定しないとロード時に例外が発生する
83 this.imageSource.Unlock();
85 image.Source = this.imageSource;
88 private void GetDpi(out int dpix, out int dpiy)
90 IntPtr hDc = NativeMethods.GetDC(IntPtr.Zero);
91 dpix = NativeMethods.GetDeviceCaps(hDc, NativeMethods.LOGPIXELSX);
92 dpiy = NativeMethods.GetDeviceCaps(hDc, NativeMethods.LOGPIXELSY);
93 NativeMethods.ReleaseDC(IntPtr.Zero, hDc);
96 public TextAntialiasMode TextAntialiasMode
100 return this.common.TextAntialiasMode;
104 this.common.TextAntialiasMode = value;
108 public bool ShowFullSpace
112 return this.common.ShowFullSpace;
116 this.common.ShowFullSpace = value;
120 public bool ShowHalfSpace
124 return this.common.ShowHalfSpace;
128 this.common.ShowHalfSpace = value;
136 return this.common.ShowTab;
140 this.common.ShowTab = value;
144 public FontFamily FontFamily
146 get { return this.fontFamily; }
149 this.fontFamily = value;
150 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
151 this.TabWidthChar = this.TabWidthChar;
155 public double FontSize
157 get { return this.fontSize; }
160 this.fontSize = value;
161 this.common.InitTextFormat(this.fontFamily.Source, (float)value, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
162 this.TabWidthChar = this.TabWidthChar;
166 public FontWeight FontWeigth
170 return this.fontWeigth;
174 this.fontWeigth = value;
175 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(value),this.GetDWFontStyle(this.fontStyle));
179 public FontStyle FontStyle
183 return this.fontStyle;
187 this.fontStyle = value;
188 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
192 public bool RightToLeft
196 return this.common.RightToLeft;
200 this.common.RightToLeft = value;
204 Color4 ToColor4(System.Windows.Media.Color color)
206 return new Color4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f);
209 public System.Windows.Media.Color Foreground
213 return this.ForegroundColor;
217 this.ForegroundColor = value;
218 this.common.Foreground = this.ToColor4(value);
222 public System.Windows.Media.Color Background
226 return this.BackgroundColor;
230 this.BackgroundColor = value;
231 this.common.Background = this.ToColor4(value);
235 public System.Windows.Media.Color InsertCaret
239 return this.InsertCaretColor;
243 this.InsertCaretColor = value;
244 this.common.InsertCaret = this.ToColor4(value);
248 public System.Windows.Media.Color OverwriteCaret
252 return this.OverwriteCaretColor;
256 this.OverwriteCaretColor = value;
257 this.common.OverwriteCaret = this.ToColor4(value);
261 public System.Windows.Media.Color LineMarker
265 return this.LineMarkerColor;
269 this.LineMarkerColor = value;
270 this.common.LineMarker = this.ToColor4(value);
274 public System.Windows.Media.Color ControlChar
278 return this.ControlCharColor;
282 this.ControlCharColor = value;
283 this.common.ControlChar = this.ToColor4(value);
287 public System.Windows.Media.Color Url
291 return this.UrlColor;
295 this.UrlColor = value;
296 this.common.Url = this.ToColor4(value);
300 public System.Windows.Media.Color Hilight
304 return this.HilightColor;
308 this.HilightColor = value;
309 this.common.Hilight = this.ToColor4(this.HilightColor);
313 public System.Windows.Media.Color Comment
317 return this.CommentColor;
321 this.CommentColor = value;
322 this.common.Comment = this.ToColor4(value);
326 public System.Windows.Media.Color Literal
330 return this.LiteralColor;
334 this.LiteralColor = value;
335 this.common.Literal = this.ToColor4(value);
339 public System.Windows.Media.Color Keyword1
343 return this.Keyword1Color;
347 this.Keyword1Color = value;
348 this.common.Keyword1 = this.ToColor4(value);
352 public System.Windows.Media.Color Keyword2
356 return this.Keyword2Color;
360 this.Keyword2Color = value;
361 this.common.Keyword2 = this.ToColor4(value);
365 public Rectangle TextArea
367 get { return this.common.ClipRect; }
368 set { this.common.ClipRect = value; }
371 public double LineNemberWidth
375 return this.common.LineNemberWidth;
379 public double FoldingWidth
383 return this.common.FoldingWidth;
387 public int TabWidthChar
389 get { return this.common.TabWidthChar; }
394 this.common.TabWidthChar = value;
402 return this.common.emSize;
406 public event ChangedRenderResourceEventHandler ChangedRenderResource
410 this.common.ChangedRenderResource += value;
414 this.common.ChangedRenderResource -= value;
418 public event EventHandler ChangedRightToLeft
422 this.common.ChangedRightToLeft += value;
426 this.common.ChangedRightToLeft -= value;
430 public bool Resize(double width, double height)
432 if (width != this.imageSource.Width || height != this.imageSource.Height)
434 this.common.ReConstructDeviceResource(width, height);
435 this.imageSource.Lock();
436 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer);
437 this.imageSource.Unlock();
443 public void DrawCachedBitmap(Rectangle rect)
445 this.common.DrawCachedBitmap(rect);
448 public void CacheContent()
450 this.common.CacheContent();
453 public bool IsVaildCache()
455 return this.common.IsVaildCache();
458 public void BegineDraw()
460 this.common.BegineDraw();
463 public void EndDraw()
465 this.common.EndDraw();
468 if (this.imageSource.IsFrontBufferAvailable)
470 this.imageSource.Lock();
471 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer);
472 this.imageSource.AddDirtyRect(new Int32Rect(0, 0, (int)this.imageSource.Width, (int)this.imageSource.Height));
473 this.imageSource.Unlock();
477 public void DrawString(string str, double x, double y, StringAlignment align, Size layoutRect)
479 this.common.DrawString(str, x, y,align,layoutRect);
482 public void FillRectangle(Rectangle rect,FillRectType type)
484 this.common.FillRectangle(rect, type);
487 public void DrawFoldingMark(bool expand, double x, double y)
489 this.common.DrawFoldingMark(expand, x, y);
492 public void FillBackground(Rectangle rect)
494 this.common.FillBackground(rect);
497 public void DrawLine(Point from, Point to)
499 this.common.DrawLine(from, to);
502 public void DrawOneLine(LineToIndexTable lti, int row, double x, double y, IEnumerable<Selection> SelectRanges)
504 PreDrawOneLineHandler PreDrawOneLine = (layout) => {
505 using (Unlocker locker = this.store.LockDocument(false))
507 int lineIndex = lti.GetIndexFromLineNumber(row);
508 int lineLength = lti.GetLengthFromLineNumber(row);
509 foreach (TextDisplayAttribute attr in this.store.EnumAttributes(lineIndex,lineIndex + lineLength))
511 if (attr.startIndex == attr.endIndex)
513 int length = attr.endIndex - attr.startIndex;
514 int start = attr.startIndex - lineIndex;
516 HilightType type = HilightType.None;
517 Color4? color = null;
518 switch (attr.attribute.lsStyle)
520 case TF_DA_LINESTYLE.TF_LS_DOT:
521 type = HilightType.Dot;
522 color = this.GetColor4(attr.attribute.crLine);
524 case TF_DA_LINESTYLE.TF_LS_SOLID:
525 type = HilightType.Sold;
526 color = this.GetColor4(attr.attribute.crLine);
528 case TF_DA_LINESTYLE.TF_LS_DASH:
529 type = HilightType.Dash;
530 color = this.GetColor4(attr.attribute.crLine);
532 case TF_DA_LINESTYLE.TF_LS_SQUIGGLE:
533 type = HilightType.Squiggle;
534 color = this.GetColor4(attr.attribute.crLine);
538 if (attr.attribute.crBk.type != TF_DA_COLORTYPE.TF_CT_NONE)
540 type = HilightType.Select;
541 color = this.GetColor4(attr.attribute.crBk);
544 this.common.DrawMarkerEffect(layout, type, start, length,x,y,attr.attribute.fBoldLine,color);
546 color = this.GetColor4(attr.attribute.crText);
549 this.common.SetTextColor(layout, start, length, color);
550 layout.Invaild = true;
555 this.common.DrawOneLine(lti,
563 private Color4? GetColor4(TF_DA_COLOR cr)
568 case TF_DA_COLORTYPE.TF_CT_SYSCOLOR:
569 colorref = new COLORREF(NativeMethods.GetSysColor((int)cr.indexOrColorRef));
571 case TF_DA_COLORTYPE.TF_CT_COLORREF:
572 colorref = new COLORREF(cr.indexOrColorRef);
577 return new Color4(colorref.R / 255.0f, colorref.G / 255.0f, colorref.B / 255.0f, 1);
580 public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges)
582 return this.common.CreateLaytout(str,syntaxCollection,MarkerRanges);
585 public List<LineToIndexTableData> BreakLine(Document doc, int startIndex, int endIndex, double wrapwidth)
587 return this.common.BreakLine(doc, startIndex, endIndex, wrapwidth);
590 public void Dispose()
592 //CA2213が表示されるが、DestructRenderHandlerで破棄しているので問題はない
593 this.common.Dispose();
594 this.DestructDevice();
597 void ReCreateTarget()
599 System.Diagnostics.Debug.WriteLine("ReCreatedDevice");
600 this.DestructDevice();
602 this.common.ReConstructDeviceResource();
605 DW.FontStyle GetDWFontStyle(FontStyle style)
607 return (DW.FontStyle)Enum.Parse(typeof(DW.FontStyle), style.ToString());
610 DW.FontWeight GetDWFontWeigth(FontWeight weigth)
612 return (DW.FontWeight)Enum.Parse(typeof(DW.FontWeight), weigth.ToString());
617 D3D10.FeatureLevel[] levels = new D3D10.FeatureLevel[]{D3D10.FeatureLevel.Level_10_1,
618 D3D10.FeatureLevel.Level_10_0,
619 D3D10.FeatureLevel.Level_9_3,
620 D3D10.FeatureLevel.Level_9_2,
621 D3D10.FeatureLevel.Level_9_1};
622 foreach (D3D10.FeatureLevel level in levels)
626 this.device = new D3D10.Device1(D3D10.DriverType.Hardware, D3D10.DeviceCreationFlags.BgraSupport,level);
634 if (this.device == null)
635 throw new PlatformNotSupportedException("DirectX10デバイスの作成に失敗しました");
637 IntPtr DesktopWnd = NativeMethods.GetDesktopWindow();
638 D3D9.Direct3DEx d3dex = new D3D9.Direct3DEx();
640 D3D9.PresentParameters param = new D3D9.PresentParameters();
641 param.Windowed = true;
642 param.SwapEffect = D3D9.SwapEffect.Discard;
643 param.DeviceWindowHandle = DesktopWnd;
644 param.PresentationInterval = D3D9.PresentInterval.Default;
648 this.device9 = new D3D9.DeviceEx(
651 D3D9.DeviceType.Hardware,
653 D3D9.CreateFlags.HardwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,
660 this.device9 = new D3D9.DeviceEx(
663 D3D9.DeviceType.Hardware,
665 D3D9.CreateFlags.SoftwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,
670 throw new PlatformNotSupportedException("DirectX9デバイスの作成に失敗しました");
679 void DestructDevice()
681 if (this.device != null)
683 this.device.Dispose();
686 if (this.device9 != null)
688 this.device9.Dispose();
693 D2D.RenderTarget ConstructRenderHandler(D2D.Factory factory, D2D.RenderTargetProperties prop, double width, double height)
695 D3D10.Texture2DDescription desc = new D3D10.Texture2DDescription();
696 desc.Width = (int)width;
697 desc.Height = (int)height;
700 desc.Format = DXGI.Format.B8G8R8A8_UNorm;
701 desc.SampleDescription = new DXGI.SampleDescription(1, 0);
702 desc.Usage = D3D10.ResourceUsage.Default;
703 desc.BindFlags = D3D10.BindFlags.RenderTarget | D3D10.BindFlags.ShaderResource;
704 desc.CpuAccessFlags = D3D10.CpuAccessFlags.None;
705 desc.OptionFlags = D3D10.ResourceOptionFlags.Shared;
706 this.texture = new D3D10.Texture2D(this.device, desc);
708 this.surface = this.texture.QueryInterface<DXGI.Surface>();
710 DXGI.Resource resource = this.texture.QueryInterface<DXGI.Resource>();
711 IntPtr handel = resource.SharedHandle;
712 D3D9.Texture texture = new D3D9.Texture(
714 this.texture.Description.Width,
715 this.texture.Description.Height,
717 D3D9.Usage.RenderTarget,
718 D3D9.Format.A8R8G8B8,
721 this.surface9 = texture.GetSurfaceLevel(0);
725 this.render = new D2D.RenderTarget(factory, this.surface, prop);
729 void ConstructedResourceHandler()
731 this.common.Foreground = this.ToColor4(this.ForegroundColor);
732 this.common.Background = this.ToColor4(this.BackgroundColor);
733 this.common.ControlChar = this.ToColor4(this.ControlCharColor);
734 this.common.Url = this.ToColor4(this.UrlColor);
735 this.common.Keyword1 = this.ToColor4(this.Keyword1Color);
736 this.common.Keyword2 = this.ToColor4(this.Keyword2Color);
737 this.common.Literal = this.ToColor4(this.LiteralColor);
738 this.common.Comment = this.ToColor4(this.CommentColor);
739 this.common.Hilight = this.ToColor4(this.HilightColor);
740 this.common.LineMarker = this.ToColor4(this.LineMarkerColor);
741 this.common.InsertCaret = this.ToColor4(this.InsertCaretColor);
742 this.common.OverwriteCaret = this.ToColor4(this.OverwriteCaretColor);
745 void DestructRenderHandler()
747 if (this.texture != null)
748 this.texture.Dispose();
749 if (this.surface != null)
750 this.surface.Dispose();
751 if (this.surface9 != null)
752 this.surface9.Dispose();
753 if (this.render != null)
754 this.render.Dispose();