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 : IEditorRender, 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 float dpix, out float 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 bool ShowLineBreak
148 return this.common.ShowLineBreak;
152 this.common.ShowLineBreak = value;
156 public FontFamily FontFamily
158 get { return this.fontFamily; }
161 this.fontFamily = value;
162 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
163 this.TabWidthChar = this.TabWidthChar;
167 public double FontSize
169 get { return this.fontSize; }
172 this.fontSize = value;
173 this.common.InitTextFormat(this.fontFamily.Source, (float)value, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
174 this.TabWidthChar = this.TabWidthChar;
178 public FontWeight FontWeigth
182 return this.fontWeigth;
186 this.fontWeigth = value;
187 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(value),this.GetDWFontStyle(this.fontStyle));
191 public FontStyle FontStyle
195 return this.fontStyle;
199 this.fontStyle = value;
200 this.common.InitTextFormat(this.fontFamily.Source, (float)this.fontSize, this.GetDWFontWeigth(this.fontWeigth), this.GetDWFontStyle(this.fontStyle));
204 public bool RightToLeft
208 return this.common.RightToLeft;
212 this.common.RightToLeft = value;
216 Color4 ToColor4(System.Windows.Media.Color color)
218 return new Color4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f);
221 public System.Windows.Media.Color Foreground
225 return this.ForegroundColor;
229 this.ForegroundColor = value;
230 this.common.Foreground = this.ToColor4(value);
234 public System.Windows.Media.Color Background
238 return this.BackgroundColor;
242 this.BackgroundColor = value;
243 this.common.Background = this.ToColor4(value);
247 public System.Windows.Media.Color InsertCaret
251 return this.InsertCaretColor;
255 this.InsertCaretColor = value;
256 this.common.InsertCaret = this.ToColor4(value);
260 public System.Windows.Media.Color OverwriteCaret
264 return this.OverwriteCaretColor;
268 this.OverwriteCaretColor = value;
269 this.common.OverwriteCaret = this.ToColor4(value);
273 public System.Windows.Media.Color LineMarker
277 return this.LineMarkerColor;
281 this.LineMarkerColor = value;
282 this.common.LineMarker = this.ToColor4(value);
286 public System.Windows.Media.Color ControlChar
290 return this.ControlCharColor;
294 this.ControlCharColor = value;
295 this.common.ControlChar = this.ToColor4(value);
299 public System.Windows.Media.Color Url
303 return this.UrlColor;
307 this.UrlColor = value;
308 this.common.Url = this.ToColor4(value);
312 public System.Windows.Media.Color Hilight
316 return this.HilightColor;
320 this.HilightColor = value;
321 this.common.Hilight = this.ToColor4(this.HilightColor);
325 public System.Windows.Media.Color Comment
329 return this.CommentColor;
333 this.CommentColor = value;
334 this.common.Comment = this.ToColor4(value);
338 public System.Windows.Media.Color Literal
342 return this.LiteralColor;
346 this.LiteralColor = value;
347 this.common.Literal = this.ToColor4(value);
351 public System.Windows.Media.Color Keyword1
355 return this.Keyword1Color;
359 this.Keyword1Color = value;
360 this.common.Keyword1 = this.ToColor4(value);
364 public System.Windows.Media.Color Keyword2
368 return this.Keyword2Color;
372 this.Keyword2Color = value;
373 this.common.Keyword2 = this.ToColor4(value);
377 public Rectangle TextArea
379 get { return this.common.ClipRect; }
380 set { this.common.ClipRect = value; }
383 public double LineNemberWidth
387 return this.common.LineNemberWidth;
391 public double FoldingWidth
395 return this.common.FoldingWidth;
399 public int TabWidthChar
401 get { return this.common.TabWidthChar; }
406 this.common.TabWidthChar = value;
414 return this.common.emSize;
418 public event ChangedRenderResourceEventHandler ChangedRenderResource
422 this.common.ChangedRenderResource += value;
426 this.common.ChangedRenderResource -= value;
430 public event EventHandler ChangedRightToLeft
434 this.common.ChangedRightToLeft += value;
438 this.common.ChangedRightToLeft -= value;
442 public bool Resize(double width, double height)
444 if (width != this.imageSource.Width || height != this.imageSource.Height)
446 this.common.ReConstructDeviceResource(width, height);
447 this.imageSource.Lock();
448 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer);
449 this.imageSource.Unlock();
455 public void DrawCachedBitmap(Rectangle rect)
457 this.common.DrawCachedBitmap(rect);
460 public void CacheContent()
462 this.common.CacheContent();
465 public bool IsVaildCache()
467 return this.common.IsVaildCache();
470 public void BegineDraw()
472 this.common.BegineDraw();
475 public void EndDraw()
477 this.common.EndDraw();
480 if (this.imageSource.IsFrontBufferAvailable)
482 this.imageSource.Lock();
483 this.imageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, this.surface9.NativePointer);
484 this.imageSource.AddDirtyRect(new Int32Rect(0, 0, (int)this.imageSource.Width, (int)this.imageSource.Height));
485 this.imageSource.Unlock();
489 public void DrawString(string str, double x, double y, StringAlignment align, Size layoutRect)
491 this.common.DrawString(str, x, y,align,layoutRect);
494 public void FillRectangle(Rectangle rect,FillRectType type)
496 this.common.FillRectangle(rect, type);
499 public void DrawFoldingMark(bool expand, double x, double y)
501 this.common.DrawFoldingMark(expand, x, y);
504 public void FillBackground(Rectangle rect)
506 this.common.FillBackground(rect);
509 public void DrawLine(Point from, Point to)
511 this.common.DrawLine(from, to);
514 public void DrawOneLine(LineToIndexTable lti, int row, double x, double y, IEnumerable<Selection> SelectRanges)
516 PreDrawOneLineHandler PreDrawOneLine = (layout) => {
517 using (Unlocker locker = this.store.LockDocument(false))
519 int lineIndex = lti.GetIndexFromLineNumber(row);
520 int lineLength = lti.GetLengthFromLineNumber(row);
521 foreach (TextDisplayAttribute attr in this.store.EnumAttributes(lineIndex,lineIndex + lineLength))
523 if (attr.startIndex == attr.endIndex)
525 int length = attr.endIndex - attr.startIndex;
526 int start = attr.startIndex - lineIndex;
528 HilightType type = HilightType.None;
529 Color4? color = null;
530 switch (attr.attribute.lsStyle)
532 case TF_DA_LINESTYLE.TF_LS_DOT:
533 type = HilightType.Dot;
534 color = this.GetColor4(attr.attribute.crLine);
536 case TF_DA_LINESTYLE.TF_LS_SOLID:
537 type = HilightType.Sold;
538 color = this.GetColor4(attr.attribute.crLine);
540 case TF_DA_LINESTYLE.TF_LS_DASH:
541 type = HilightType.Dash;
542 color = this.GetColor4(attr.attribute.crLine);
544 case TF_DA_LINESTYLE.TF_LS_SQUIGGLE:
545 type = HilightType.Squiggle;
546 color = this.GetColor4(attr.attribute.crLine);
550 if (attr.attribute.crBk.type != TF_DA_COLORTYPE.TF_CT_NONE)
552 type = HilightType.Select;
553 color = this.GetColor4(attr.attribute.crBk);
556 this.common.DrawMarkerEffect(layout, type, start, length,x,y,attr.attribute.fBoldLine,color);
558 color = this.GetColor4(attr.attribute.crText);
561 this.common.SetTextColor(layout, start, length, color);
562 layout.Invaild = true;
567 this.common.DrawOneLine(lti,
575 private Color4? GetColor4(TF_DA_COLOR cr)
580 case TF_DA_COLORTYPE.TF_CT_SYSCOLOR:
581 colorref = new COLORREF(NativeMethods.GetSysColor((int)cr.indexOrColorRef));
583 case TF_DA_COLORTYPE.TF_CT_COLORREF:
584 colorref = new COLORREF(cr.indexOrColorRef);
589 return new Color4(colorref.R / 255.0f, colorref.G / 255.0f, colorref.B / 255.0f, 1);
592 public ITextLayout CreateLaytout(string str, SyntaxInfo[] syntaxCollection, IEnumerable<Marker> MarkerRanges)
594 return this.common.CreateLaytout(str,syntaxCollection,MarkerRanges);
597 public List<LineToIndexTableData> BreakLine(Document doc,LineToIndexTable layoutLineCollection, int startIndex, int endIndex, double wrapwidth)
599 return this.common.BreakLine(doc,layoutLineCollection, startIndex, endIndex, wrapwidth);
602 public void Dispose()
604 //CA2213が表示されるが、DestructRenderHandlerで破棄しているので問題はない
605 this.common.Dispose();
606 this.DestructDevice();
609 void ReCreateTarget()
611 System.Diagnostics.Debug.WriteLine("ReCreatedDevice");
612 this.DestructDevice();
614 this.common.ReConstructDeviceResource();
617 DW.FontStyle GetDWFontStyle(FontStyle style)
619 return (DW.FontStyle)Enum.Parse(typeof(DW.FontStyle), style.ToString());
622 DW.FontWeight GetDWFontWeigth(FontWeight weigth)
624 return (DW.FontWeight)Enum.Parse(typeof(DW.FontWeight), weigth.ToString());
629 D3D10.FeatureLevel[] levels = new D3D10.FeatureLevel[]{D3D10.FeatureLevel.Level_10_1,
630 D3D10.FeatureLevel.Level_10_0,
631 D3D10.FeatureLevel.Level_9_3,
632 D3D10.FeatureLevel.Level_9_2,
633 D3D10.FeatureLevel.Level_9_1};
634 foreach (D3D10.FeatureLevel level in levels)
638 this.device = new D3D10.Device1(D3D10.DriverType.Hardware, D3D10.DeviceCreationFlags.BgraSupport,level);
646 if (this.device == null)
647 throw new PlatformNotSupportedException("DirectX10デバイスの作成に失敗しました");
649 IntPtr DesktopWnd = NativeMethods.GetDesktopWindow();
650 D3D9.Direct3DEx d3dex = new D3D9.Direct3DEx();
652 D3D9.PresentParameters param = new D3D9.PresentParameters();
653 param.Windowed = true;
654 param.SwapEffect = D3D9.SwapEffect.Discard;
655 param.DeviceWindowHandle = DesktopWnd;
656 param.PresentationInterval = D3D9.PresentInterval.Default;
660 this.device9 = new D3D9.DeviceEx(
663 D3D9.DeviceType.Hardware,
665 D3D9.CreateFlags.HardwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,
672 this.device9 = new D3D9.DeviceEx(
675 D3D9.DeviceType.Hardware,
677 D3D9.CreateFlags.SoftwareVertexProcessing | D3D9.CreateFlags.Multithreaded | D3D9.CreateFlags.FpuPreserve,
682 throw new PlatformNotSupportedException("DirectX9デバイスの作成に失敗しました");
691 void DestructDevice()
693 if (this.device != null)
695 this.device.Dispose();
698 if (this.device9 != null)
700 this.device9.Dispose();
705 D2D.RenderTarget ConstructRenderHandler(D2D.Factory factory, D2D.RenderTargetProperties prop, double width, double height)
707 D3D10.Texture2DDescription desc = new D3D10.Texture2DDescription();
708 desc.Width = (int)width;
709 desc.Height = (int)height;
712 desc.Format = DXGI.Format.B8G8R8A8_UNorm;
713 desc.SampleDescription = new DXGI.SampleDescription(1, 0);
714 desc.Usage = D3D10.ResourceUsage.Default;
715 desc.BindFlags = D3D10.BindFlags.RenderTarget | D3D10.BindFlags.ShaderResource;
716 desc.CpuAccessFlags = D3D10.CpuAccessFlags.None;
717 desc.OptionFlags = D3D10.ResourceOptionFlags.Shared;
718 this.texture = new D3D10.Texture2D(this.device, desc);
720 this.surface = this.texture.QueryInterface<DXGI.Surface>();
722 DXGI.Resource resource = this.texture.QueryInterface<DXGI.Resource>();
723 IntPtr handel = resource.SharedHandle;
724 D3D9.Texture texture = new D3D9.Texture(
726 this.texture.Description.Width,
727 this.texture.Description.Height,
729 D3D9.Usage.RenderTarget,
730 D3D9.Format.A8R8G8B8,
733 this.surface9 = texture.GetSurfaceLevel(0);
737 this.render = new D2D.RenderTarget(factory, this.surface, prop);
741 void ConstructedResourceHandler()
743 this.common.Foreground = this.ToColor4(this.ForegroundColor);
744 this.common.Background = this.ToColor4(this.BackgroundColor);
745 this.common.ControlChar = this.ToColor4(this.ControlCharColor);
746 this.common.Url = this.ToColor4(this.UrlColor);
747 this.common.Keyword1 = this.ToColor4(this.Keyword1Color);
748 this.common.Keyword2 = this.ToColor4(this.Keyword2Color);
749 this.common.Literal = this.ToColor4(this.LiteralColor);
750 this.common.Comment = this.ToColor4(this.CommentColor);
751 this.common.Hilight = this.ToColor4(this.HilightColor);
752 this.common.LineMarker = this.ToColor4(this.LineMarkerColor);
753 this.common.InsertCaret = this.ToColor4(this.InsertCaretColor);
754 this.common.OverwriteCaret = this.ToColor4(this.OverwriteCaretColor);
757 void DestructRenderHandler()
759 if (this.texture != null)
760 this.texture.Dispose();
761 if (this.surface != null)
762 this.surface.Dispose();
763 if (this.surface9 != null)
764 this.surface9.Dispose();
765 if (this.render != null)
766 this.render.Dispose();