namespace FooEditEngine
{
class TextRender
{
/// <summary>
/// (X,Y)に文字列を描く
/// </summary>
/// <param name="str">文字列</param>
/// <param name="x">X座標</param>
/// <param name="y">Y座標</param>
public void DrawString(string str, int x, int y)
{
int letterwidth = this.Graphics.GetStringWidth(" ");
int ClipWidthChars = ( 0 - x + this.ClipRect.Width) / letterwidth + 50;
int xpos = x;
TextRunCollection runs = new TextRunCollection(str, this.SelectRange,this.Hilighter,ClipWidthChars);
foreach (TextRun run in runs)
{
//this.Graphics.DrawStringは文字列を描くメソッド
if (run.str == "\t")
this.Graphics.DrawString(this.GetExpandedTab(0),this.TabWidth - ((xpos - x) % this.TabWidth), TokenType.Control, run.hilight,ref xpos,ref y);
else if (run.str == Document.InternalNewLine.ToString())
this.Graphics.DrawString(NewLineSymbol, TokenType.Control, run.hilight, ref xpos, ref y);
else if (run.str == Document.EndOfFile.ToString())
this.Graphics.DrawString(EndOfFileSymbol, TokenType.Control, run.hilight, ref xpos, ref y);
else
this.Graphics.DrawString(run.str, run.token, run.hilight, ref xpos, ref y);
if (xpos > this.ClipRect.Right)
break;
}
}
}
internal struct TextRun
{
public string str;
public int index;
public HilightType hilight;
public TokenType token;
public TextRun(string str, HilightType hilight,int index)
{
this.str = str;
this.hilight = hilight;
this.index = index;
this.token = TokenType.None;
}
public TextRun(string str, HilightType hilight,TokenType token, int index)
{
this.str = str;
this.hilight = hilight;
this.index = index;
this.token = token;
}
}
internal class TextRunCollection : IEnumerable<TextRun>
{
List<TextRun> runs = new List<TextRun>();
public TextRunCollection(string str, Selection selection,IHilighter hilighter,int clipwidthchars)
{
StringBuilder margedstr = new StringBuilder();
HilightType oldSelected = HilightType.None,isSelected = HilightType.None;
int startRun = 0;
for (int i = 0; i < str.Length && i < clipwidthchars; i++)
{
oldSelected = isSelected;
isSelected = this.isSelected(i,selection) ? HilightType.Select : HilightType.None;
if (str[i] != '\t' && str[i] != Document.InternalNewLine && str[i] != Document.EndOfFile && isSelected == oldSelected)
{
margedstr.Append(str[i]);
continue;
}
if (margedstr.Length > 0)
{
this.runs.Add(new TextRun(margedstr.ToString(), oldSelected,startRun));
margedstr.Clear();
}
startRun = i;
if(str[i] == '\t' || str[i] == Document.InternalNewLine || str[i] == Document.EndOfFile)
this.runs.Add(new TextRun(str[i].ToString(), isSelected,i));
else
margedstr.Append(str[i]);
}
if (margedstr.Length > 0)
this.runs.Add(new TextRun(margedstr.ToString(), isSelected,startRun));
}
}
}