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 SharpDX.Mathematics.Interop.RawBool isTrailing, isInsed;
101 DW.HitTestMetrics metrics;
102 metrics = this.layout.HitTestPoint((float)x, 0, out isTrailing, out isInsed);
105 index = metrics.TextPosition + metrics.Length;
107 index = metrics.TextPosition;
108 if (this.ShowLineBreak && index == this.lineBreakIndex + 1) //改行マークの後ろにヒットしたら
113 public double GetWidthFromIndex(int index)
116 DW.HitTestMetrics metrics;
117 metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
119 layout.HitTestTextPosition(index, true, out x2, out y);
124 public double GetColPostionFromIndex(int index)
127 DW.HitTestMetrics metrics;
128 metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
132 public int AlignIndexToNearestCluster(int index, AlignDirection flow)
135 DW.HitTestMetrics metrics;
136 metrics = this.layout.HitTestTextPosition(index, false, out x, out y);
138 if (flow == AlignDirection.Forward)
139 return Util.RoundUp(metrics.TextPosition + metrics.Length);
140 else if (flow == AlignDirection.Back)
141 return Util.RoundUp(metrics.TextPosition);
142 throw new ArgumentOutOfRangeException();
149 if(double.IsNaN(this._width))
150 this._width = Util.RoundUp(this.layout.Metrics.WidthIncludingTrailingWhitespace);
159 if (!double.IsNaN(this._height))
161 this._height = Util.RoundUp(layout.Metrics.Height);
166 public StringAlignment StringAlignment
170 return this._strAlign;
174 this._strAlign = value;
177 case StringAlignment.Left:
178 layout.TextAlignment = DW.TextAlignment.Leading;
180 case StringAlignment.Center:
181 layout.TextAlignment = DW.TextAlignment.Center;
183 case StringAlignment.Right:
184 layout.TextAlignment = DW.TextAlignment.Trailing;
190 public void Draw(DW.TextRenderer render, float x, float y)
192 this.layout.Draw(render, x, y);
195 public void Draw(D2D.RenderTarget render, float x, float y, D2D.Brush brush)
197 render.DrawTextLayout(new Vector2((float)x, (float)y), this.layout, brush);
200 public void Dispose()
202 this.layout.Dispose();
203 this.Disposed = true;
206 public void SetDrawingEffect(ComObject resource, DW.TextRange range)
208 this.layout.SetDrawingEffect(resource, range);
211 public void SetLineBreakBrush(D2D.Brush brush)
213 if(this.ShowLineBreak)
214 this.layout.SetDrawingEffect(brush, new DW.TextRange(lineBreakIndex, 1));
217 public void SetUnderline(bool underline, DW.TextRange range)
219 this.layout.SetUnderline(underline, range);
222 public DW.HitTestMetrics[] HitTestTextRange(int start, int length, float x, float y)
224 return this.layout.HitTestTextRange(start, length, x, y);
227 public void SetInlineObject(DW.InlineObject o, DW.TextRange range)
229 this.layout.SetInlineObject(o, range);