OSDN Git Service

レンダーターゲットをクラス変数として持たせておく意味はない
[fooeditengine/FooEditEngine.git] / Core / Direct2D / CustomTextRenderer.cs
1 /*
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.
5
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.
8
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/>.
10  */
11 using System;
12 using SharpDX;
13 using D2D = SharpDX.Direct2D1;
14 using DW = SharpDX.DirectWrite;
15
16 namespace FooEditEngine
17 {
18     sealed class CustomTextRenderer : CallbackBase, DW.TextRenderer
19     {
20         ColorBrushCollection brushes;
21         StrokeCollection strokes;
22
23         public CustomTextRenderer(ColorBrushCollection brushes,StrokeCollection strokes,Color4 defalut)
24         {
25             this.DefaultFore = defalut;
26             this.brushes = brushes;
27             this.strokes = strokes;
28         }
29
30         public Color4 DefaultFore
31         {
32             get;
33             set;
34         }
35
36         #region TextRenderer Members
37
38         public Result DrawGlyphRun(object clientDrawingContext, float baselineOriginX, float baselineOriginY, D2D.MeasuringMode measuringMode, DW.GlyphRun glyphRun, DW.GlyphRunDescription glyphRunDescription, ComObject clientDrawingEffect)
39         {
40             D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
41             if (render == null)
42                 return SharpDX.Result.Ok;
43
44             D2D.SolidColorBrush foreBrush = this.brushes.Get(render, this.DefaultFore);
45             bool isDrawGlyphRun = true;
46             if (clientDrawingEffect != null)
47             {
48                 var drawingForeBrush = clientDrawingEffect as D2D.SolidColorBrush;
49                 var selectedEffect = clientDrawingEffect as SelectedEffect;
50                 var drawingEffect = clientDrawingEffect as DrawingEffect;
51
52                 if (drawingForeBrush != null)
53                 {
54                     foreBrush = drawingForeBrush;
55                 }
56                 else if(selectedEffect != null)
57                 {
58                     foreBrush = this.brushes.Get(render, selectedEffect.Fore);
59                 }
60                 else if (drawingEffect != null)
61                 {
62                     if (drawingEffect.Stroke == HilightType.Url)
63                         foreBrush = this.brushes.Get(render, drawingEffect.Fore);
64                 }
65             }
66
67             if(isDrawGlyphRun)
68                 render.DrawGlyphRun(new Vector2(baselineOriginX, baselineOriginY),
69                     glyphRun,
70                     foreBrush,
71                     measuringMode);
72
73             return SharpDX.Result.Ok;
74         }
75
76         RectangleF GetGlyphBound(DW.GlyphRun myGlyphRun, float baselineOriginX, float baselineOriginY,bool underline = false)
77         {
78             RectangleF bounds = new RectangleF();
79
80             DW.FontMetrics fontMetrics = myGlyphRun.FontFace.Metrics;
81
82             float ascentPixel = myGlyphRun.FontSize * fontMetrics.Ascent / fontMetrics.DesignUnitsPerEm;
83             float dscentPixel = underline ?
84                 myGlyphRun.FontSize * (fontMetrics.Descent + fontMetrics.LineGap + fontMetrics.UnderlinePosition) / fontMetrics.DesignUnitsPerEm : 
85                 myGlyphRun.FontSize * (fontMetrics.Descent + fontMetrics.LineGap) / fontMetrics.DesignUnitsPerEm;
86
87             float right = baselineOriginX;
88
89             int glyphCount = myGlyphRun.Advances.Length;
90
91             for (int i = 0; i < glyphCount; i++)
92             {
93                 if (myGlyphRun.BidiLevel % 2 == 1)
94                     right -= myGlyphRun.Advances[i];
95                 else
96                     right += myGlyphRun.Advances[i];
97             }
98
99             bounds.Left = baselineOriginX;
100             if (glyphCount > 0)
101                 bounds.Right = right;
102             else if (myGlyphRun.Advances.Length == 1)
103                 bounds.Right = baselineOriginX + myGlyphRun.Advances[0];
104             else
105                 bounds.Right = bounds.Left;
106             bounds.Top = baselineOriginY - ascentPixel;
107             bounds.Bottom = baselineOriginY + dscentPixel;
108
109             return bounds;
110         }
111
112         public Result DrawInlineObject(object clientDrawingContext, float originX, float originY, DW.InlineObject inlineObject, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)
113         {
114             D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
115             if (render == null)
116                 return SharpDX.Result.Ok;
117
118             inlineObject.Draw(render, this, originX, originY, isSideways, isRightToLeft, clientDrawingEffect);
119             return Result.Ok;
120         }
121
122         public Result DrawStrikethrough(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref DW.Strikethrough strikethrough, ComObject clientDrawingEffect)
123         {
124             D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
125             if (render == null)
126                 return SharpDX.Result.Ok;
127
128             D2D.SolidColorBrush foreBrush = this.brushes.Get(render, this.DefaultFore);
129             DrawingEffect effect = clientDrawingEffect as DrawingEffect;
130             if (clientDrawingEffect != null && clientDrawingEffect != null)
131             {
132                 foreBrush = this.brushes.Get(render, effect.Fore);
133             }
134             if (effect == null)
135             {
136                 render.DrawLine(new Vector2(baselineOriginX, baselineOriginY + strikethrough.Offset),
137                     new Vector2(baselineOriginX + strikethrough.Width - 1, baselineOriginY + strikethrough.Offset),
138                     foreBrush,
139                     GetThickness(render, strikethrough.Thickness));
140             }
141             return Result.Ok;
142         }
143
144         public Result DrawUnderline(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref DW.Underline underline, ComObject clientDrawingEffect)
145         {
146             D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
147             if (render == null)
148                 return SharpDX.Result.Ok;
149
150             D2D.SolidColorBrush foreBrush = this.brushes.Get(render, this.DefaultFore);
151             DrawingEffect effect = clientDrawingEffect as DrawingEffect;
152             if (clientDrawingEffect != null && effect != null)
153             {
154                 foreBrush = this.brushes.Get(render, effect.Fore);
155                 float thickness = effect.isBoldLine ? D2DRenderCommon.BoldThickness : D2DRenderCommon.NormalThickness;
156                 if (effect.Stroke == HilightType.Squiggle)
157                 {
158                     SquilleLineMarker marker = new D2DSquilleLineMarker(render, this.brushes.Get(render, effect.Fore), this.strokes.Get(render,effect.Stroke), 1);
159                     marker.Draw(
160                         baselineOriginX, baselineOriginY + underline.Offset,
161                         underline.Width, underline.RunHeight
162                         );
163                 }
164                 else
165                 {
166                     LineMarker marker = new LineMarker(render, this.brushes.Get(render, effect.Fore), this.strokes.Get(render,effect.Stroke), GetThickness(render, thickness));
167                     marker.Draw(
168                         baselineOriginX, baselineOriginY + underline.Offset,
169                         underline.Width, 0
170                         );
171                 }
172             }
173             if (effect == null)
174             {
175                 render.DrawLine(new Vector2(baselineOriginX, baselineOriginY + underline.Offset),
176                     new Vector2(baselineOriginX + underline.Width - 1, baselineOriginY + underline.Offset),
177                     foreBrush,
178                     GetThickness(render,underline.Thickness));
179             }
180
181             return SharpDX.Result.Ok;
182         }
183
184         #endregion
185
186         #region PixelSnapping Members
187
188         public SharpDX.Mathematics.Interop.RawMatrix3x2 GetCurrentTransform(object clientDrawingContext)
189         {
190             D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
191             if (render == null)
192                 throw new InvalidOperationException("render is null");
193
194             SharpDX.Mathematics.Interop.RawMatrix3x2 d2Dmatrix = render.Transform;
195             return d2Dmatrix;
196         }
197
198         public float GetPixelsPerDip(object clientDrawingContext)
199         {
200             D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
201             if (render == null)
202                 throw new InvalidOperationException("render is null");
203
204             return render.PixelSize.Width / 96f;
205         }
206
207         public bool IsPixelSnappingDisabled(object clientDrawingContext)
208         {
209             return false;
210         }
211
212         #endregion
213
214         float GetThickness(D2D.RenderTarget render,float thickness)
215         {
216             if (render.AntialiasMode == D2D.AntialiasMode.Aliased)
217                 return (int)(thickness + 0.5);
218             else
219                 return thickness;
220         }
221
222     }
223 }