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