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/>.
13 using D2D = SharpDX.Direct2D1;
14 using DW = SharpDX.DirectWrite;
16 namespace FooEditEngine
18 sealed class CustomTextRenderer : CallbackBase, DW.TextRenderer
20 ColorBrushCollection brushes;
21 StrokeCollection strokes;
23 public CustomTextRenderer(ColorBrushCollection brushes,StrokeCollection strokes,Color4 defalut)
25 this.DefaultFore = defalut;
26 this.brushes = brushes;
27 this.strokes = strokes;
30 public Color4 DefaultFore
36 #region TextRenderer Members
38 public Result DrawGlyphRun(object clientDrawingContext, float baselineOriginX, float baselineOriginY, D2D.MeasuringMode measuringMode, DW.GlyphRun glyphRun, DW.GlyphRunDescription glyphRunDescription, ComObject clientDrawingEffect)
40 D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
42 return SharpDX.Result.Ok;
44 D2D.SolidColorBrush foreBrush = this.brushes.Get(render, this.DefaultFore);
45 bool isDrawGlyphRun = true;
46 if (clientDrawingEffect != null)
48 var drawingForeBrush = clientDrawingEffect as D2D.SolidColorBrush;
49 var selectedEffect = clientDrawingEffect as SelectedEffect;
50 var drawingEffect = clientDrawingEffect as DrawingEffect;
52 if (drawingForeBrush != null)
54 foreBrush = drawingForeBrush;
56 else if(selectedEffect != null)
58 foreBrush = this.brushes.Get(render, selectedEffect.Fore);
60 else if (drawingEffect != null)
62 if (drawingEffect.Stroke == HilightType.Url)
63 foreBrush = this.brushes.Get(render, drawingEffect.Fore);
68 render.DrawGlyphRun(new Vector2(baselineOriginX, baselineOriginY),
73 return SharpDX.Result.Ok;
76 RectangleF GetGlyphBound(DW.GlyphRun myGlyphRun, float baselineOriginX, float baselineOriginY,bool underline = false)
78 RectangleF bounds = new RectangleF();
80 DW.FontMetrics fontMetrics = myGlyphRun.FontFace.Metrics;
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;
87 float right = baselineOriginX;
89 int glyphCount = myGlyphRun.Advances.Length;
91 for (int i = 0; i < glyphCount; i++)
93 if (myGlyphRun.BidiLevel % 2 == 1)
94 right -= myGlyphRun.Advances[i];
96 right += myGlyphRun.Advances[i];
99 bounds.Left = baselineOriginX;
101 bounds.Right = right;
102 else if (myGlyphRun.Advances.Length == 1)
103 bounds.Right = baselineOriginX + myGlyphRun.Advances[0];
105 bounds.Right = bounds.Left;
106 bounds.Top = baselineOriginY - ascentPixel;
107 bounds.Bottom = baselineOriginY + dscentPixel;
112 public Result DrawInlineObject(object clientDrawingContext, float originX, float originY, DW.InlineObject inlineObject, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)
114 D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
116 return SharpDX.Result.Ok;
118 inlineObject.Draw(render, this, originX, originY, isSideways, isRightToLeft, clientDrawingEffect);
122 public Result DrawStrikethrough(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref DW.Strikethrough strikethrough, ComObject clientDrawingEffect)
124 D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
126 return SharpDX.Result.Ok;
128 D2D.SolidColorBrush foreBrush = this.brushes.Get(render, this.DefaultFore);
129 DrawingEffect effect = clientDrawingEffect as DrawingEffect;
130 if (clientDrawingEffect != null && clientDrawingEffect != null)
132 foreBrush = this.brushes.Get(render, effect.Fore);
136 render.DrawLine(new Vector2(baselineOriginX, baselineOriginY + strikethrough.Offset),
137 new Vector2(baselineOriginX + strikethrough.Width - 1, baselineOriginY + strikethrough.Offset),
139 GetThickness(render, strikethrough.Thickness));
144 public Result DrawUnderline(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref DW.Underline underline, ComObject clientDrawingEffect)
146 D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
148 return SharpDX.Result.Ok;
150 D2D.SolidColorBrush foreBrush = this.brushes.Get(render, this.DefaultFore);
151 DrawingEffect effect = clientDrawingEffect as DrawingEffect;
152 if (clientDrawingEffect != null && effect != null)
154 foreBrush = this.brushes.Get(render, effect.Fore);
155 float thickness = effect.isBoldLine ? D2DRenderCommon.BoldThickness : D2DRenderCommon.NormalThickness;
156 if (effect.Stroke == HilightType.Squiggle)
158 SquilleLineMarker marker = new D2DSquilleLineMarker(render, this.brushes.Get(render, effect.Fore), this.strokes.Get(render,effect.Stroke), 1);
160 baselineOriginX, baselineOriginY + underline.Offset,
161 underline.Width, underline.RunHeight
166 LineMarker marker = new LineMarker(render, this.brushes.Get(render, effect.Fore), this.strokes.Get(render,effect.Stroke), GetThickness(render, thickness));
168 baselineOriginX, baselineOriginY + underline.Offset,
175 render.DrawLine(new Vector2(baselineOriginX, baselineOriginY + underline.Offset),
176 new Vector2(baselineOriginX + underline.Width - 1, baselineOriginY + underline.Offset),
178 GetThickness(render,underline.Thickness));
181 return SharpDX.Result.Ok;
186 #region PixelSnapping Members
188 public SharpDX.Mathematics.Interop.RawMatrix3x2 GetCurrentTransform(object clientDrawingContext)
190 D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
192 throw new InvalidOperationException("render is null");
194 SharpDX.Mathematics.Interop.RawMatrix3x2 d2Dmatrix = render.Transform;
198 public float GetPixelsPerDip(object clientDrawingContext)
200 D2D.RenderTarget render = clientDrawingContext as D2D.RenderTarget;
202 throw new InvalidOperationException("render is null");
204 return render.PixelSize.Width / 96f;
207 public bool IsPixelSnappingDisabled(object clientDrawingContext)
214 float GetThickness(D2D.RenderTarget render,float thickness)
216 if (render.AntialiasMode == D2D.AntialiasMode.Aliased)
217 return (int)(thickness + 0.5);