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;
14 using D2D = SharpDX.Direct2D1;
15 using DW = SharpDX.DirectWrite;
17 namespace FooEditEngine
19 sealed class MyTextLayout : ITextLayout
21 double _height = double.NaN;
22 double _width = double.NaN;
23 int lineBreakIndex = 0;
24 StringAlignment _strAlign;
26 internal MyTextLayout(DW.Factory dwFactory,string str,DW.TextFormat format,double width,double height,float dip,bool showLineBreak)
28 if (dwFactory.IsDisposed)
30 throw new InvalidOperationException();
32 str = str.Trim(Document.NewLine); //取り除かないとキャレットの動きがおかしくなる
35 this.lineBreakIndex = str.Length;
38 this.layout = new DW.TextLayout(dwFactory,
43 this.Disposed = false;
44 this.ShowLineBreak = showLineBreak;
49 public bool ShowLineBreak
71 return this.layout.MaxWidth;
75 public float MaxHeight
79 return this.layout.MaxHeight;
83 public bool RightToLeft
87 return this.layout.ReadingDirection == DW.ReadingDirection.RightToLeft;
92 this.layout.ReadingDirection = DW.ReadingDirection.RightToLeft;
94 this.layout.ReadingDirection = DW.ReadingDirection.LeftToRight;
98 public int GetIndexFromColPostion(double x)
100 return this.GetIndexFromPostion(x, 0);
103 public double GetWidthFromIndex(int index)
106 DW.HitTestMetrics metrics;
107 metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
109 layout.HitTestTextPosition(index, true, out x2, out y);
114 public double GetColPostionFromIndex(int index)
116 Point p = this.GetPostionFromIndex(index);
120 public int GetIndexFromPostion(double x, double y)
122 SharpDX.Mathematics.Interop.RawBool isTrailing, isInsed;
123 DW.HitTestMetrics metrics;
124 metrics = this.layout.HitTestPoint((float)x, (float)y, out isTrailing, out isInsed);
127 index = metrics.TextPosition + metrics.Length;
129 index = metrics.TextPosition;
130 if (this.ShowLineBreak && index == this.lineBreakIndex + 1) //改行マークの後ろにヒットしたら
135 public Point GetPostionFromIndex(int index)
138 DW.HitTestMetrics metrics;
139 metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
140 return new Point(x,y);
143 public int AlignIndexToNearestCluster(int index, AlignDirection flow)
146 DW.HitTestMetrics metrics;
147 metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
149 if (flow == AlignDirection.Forward)
150 return Util.RoundUp(metrics.TextPosition + metrics.Length);
151 else if (flow == AlignDirection.Back)
152 return Util.RoundUp(metrics.TextPosition);
153 throw new ArgumentOutOfRangeException();
160 if(double.IsNaN(this._width))
161 this._width = Util.RoundUp(this.layout.Metrics.WidthIncludingTrailingWhitespace);
170 if (!double.IsNaN(this._height))
172 this._height = Util.RoundUp(this.layout.Metrics.Height);
177 public StringAlignment StringAlignment
181 return this._strAlign;
185 this._strAlign = value;
188 case StringAlignment.Left:
189 layout.TextAlignment = DW.TextAlignment.Leading;
191 case StringAlignment.Center:
192 layout.TextAlignment = DW.TextAlignment.Center;
194 case StringAlignment.Right:
195 layout.TextAlignment = DW.TextAlignment.Trailing;
201 public void Draw(D2D.RenderTarget d2drender, DW.TextRenderer render, float x, float y)
203 this.layout.Draw(d2drender, render, x, y);
206 public void Draw(D2D.RenderTarget render, float x, float y, D2D.Brush brush)
208 render.DrawTextLayout(new Vector2((float)x, (float)y), this.layout, brush);
211 public void Dispose()
213 this.layout.Dispose();
214 this.Disposed = true;
217 public void SetDrawingEffect(ComObject resource, DW.TextRange range)
219 this.layout.SetDrawingEffect(resource, range);
222 public void SetLineBreakBrush(D2D.Brush brush)
224 if(this.ShowLineBreak)
225 this.layout.SetDrawingEffect(brush, new DW.TextRange(lineBreakIndex, 1));
228 public void SetUnderline(bool underline, DW.TextRange range)
230 this.layout.SetUnderline(underline, range);
233 public DW.HitTestMetrics[] HitTestTextRange(int start, int length, float x, float y)
235 return this.layout.HitTestTextRange(start, length, x, y);
238 public void SetInlineObject(DW.InlineObject o, DW.TextRange range)
240 this.layout.SetInlineObject(o, range);