]> O.S.I.I.S - jp/crow.git/commitdiff
test span
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 11 Jan 2021 23:37:48 +0000 (00:37 +0100)
committerj-p <jp_bruyere@hotmail.com>
Sat, 6 Feb 2021 19:28:02 +0000 (20:28 +0100)
Crow/Crow.csproj
Crow/src/ExtensionsMethods.cs
Crow/src/Mono.Cairo/Context.cs
Crow/src/Mono.Cairo/NativeMethods.cs
Crow/src/Widgets/Label.cs
Samples/PerfTests/Properties/launchSettings.json [new file with mode: 0644]

index faede56da87f85f03c5f1ed73459452ff372a486..281e572900ade950154de3c356659052df503431 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
-               <TargetFrameworks>netstandard2.0</TargetFrameworks>
+<!--           <TargetFrameworks>netstandard2.0</TargetFrameworks>-->
+               <TargetFrameworks>netstandard2.1</TargetFrameworks>
                
                <AssemblyVersion>$(CrowVersion)</AssemblyVersion>
                <PackageVersion>$(CrowPackageVersion)</PackageVersion>
index 0ac07c11df7532a4c01d0b7ba84db70276e8a56e..a40b25fc5d0a42e862203c166f7d7c0cef344e74 100644 (file)
@@ -180,7 +180,7 @@ namespace Crow
                }
                public static bool IsWhiteSpaceOrNewLine (this char c)
                {
-                       return c == '\t' || c == '\r' || c == '\n' || char.IsWhiteSpace (c);
+                       return c == '\t' || c.IsAnyLineBreakCharacter() || char.IsWhiteSpace (c);
                }
                public static object GetDefaultValue(this object obj)
                {                       
@@ -193,6 +193,32 @@ namespace Crow
 
                public static FileSystemInfo [] GetFileSystemInfosOrdered (this DirectoryInfo di)
                        => di.GetFileSystemInfos ().OrderBy (f => f.Attributes).ThenBy (f => f.Name).ToArray ();
+
+               internal static bool IsAnyLineBreakCharacter (this char c) 
+                       => c == '\n' || c == '\r' || c == '\u0085' || c == '\u2028' || c == '\u2029';
+               internal static ReadOnlySpan<char> GetLine (this string str, LineSpan ls) {
+                       if (ls.Start >= str.Length)
+                               return "".AsSpan ();
+                       return str.AsSpan ().Slice (ls.Start, ls.Length);                               
+               }
+               internal static ReadOnlySpan<char> GetLine (this string str, LineSpan ls, int offset) {
+                       int start = ls.Start + offset;
+                       if (start >= str.Length)
+                               return "".AsSpan ();
+                       return str.AsSpan ().Slice (start, ls.Length);
+                               
+               }
+               internal static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, LineSpan ls) {
+                       if (ls.Start >= str.Length)
+                               return "".AsSpan ();
+                       return str.AsSpan ().Slice (ls.Start, ls.LengthIncludingLineBreak);
+               }
+               internal static ReadOnlySpan<char> GetLineIncludingLineBreak (this string str, LineSpan ls, int offset) {
+                       int start = ls.Start + offset;
+                       if (start >= str.Length)
+                               return "".AsSpan ();
+                       return str.AsSpan ().Slice (start, ls.LengthIncludingLineBreak);
+               }
        }
 }
 
index 6463ecf09f76984e7baad4f60385fdce5a296079..57f6c517e8e2deec4e1d1fe270ee3c0b40bacd00 100644 (file)
@@ -878,10 +878,35 @@ namespace Crow.Cairo {
                public TextExtents TextExtents(string s)
                {
                        TextExtents extents;
-                       NativeMethods.cairo_text_extents (handle, s, out extents);
+                       NativeMethods.cairo_text_extents (handle, TerminateUtf8(s), out extents);
                        return extents;
                }
+               public void ShowText (ReadOnlySpan<char> s, int tabSize) {
+                       int size = s.Length * 4 + 1;
+                       Span<byte> bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+                       int encodedBytes = Encoding.UTF8.GetBytes(s, bytes);
+                       bytes[encodedBytes] = 0;
 
+                       NativeMethods.cairo_show_text (handle, ref bytes.Slice (0, encodedBytes + 1).GetPinnableReference ());
+               }
+               public TextExtents TextExtents (ReadOnlySpan<char> s, int tabSize) {
+                       TextExtents extents;
+                       int size = s.Length * 4 + 1;
+                       Span<byte> bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+                       int encodedBytes = Encoding.UTF8.GetBytes (s, bytes);
+                       bytes[encodedBytes] = 0;
+
+                       NativeMethods.cairo_text_extents (handle, ref bytes.Slice (0, encodedBytes + 1).GetPinnableReference (), out extents);
+                       return extents;
+               }
+               public void TextExtents (ReadOnlySpan<char> s, int tabSize, out TextExtents extents) {
+                       int size = s.Length * 4 + 1;
+                       Span<byte> bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+                       int encodedBytes = Encoding.UTF8.GetBytes (s, bytes);
+                       bytes[encodedBytes] = 0;
+                       
+                       NativeMethods.cairo_text_extents (handle, ref bytes.Slice(0, encodedBytes + 1).GetPinnableReference(), out extents);
+               }
 
                public TextExtents GlyphExtents (Glyph[] glyphs)
                {
index 66b528a1cef97c08e737b0721ba2439678ea8a19..4f93c4118b621fc44db5ab6bba3a12bc9252ecbf 100644 (file)
@@ -751,9 +751,6 @@ namespace Crow.Cairo
                [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
                internal static extern void cairo_show_page (IntPtr cr);
 
-               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
-               internal static extern void cairo_show_text (IntPtr cr, byte[] text);
-
                [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
                internal static extern Status cairo_status (IntPtr cr);
 
@@ -839,8 +836,17 @@ namespace Crow.Cairo
                internal static extern IntPtr cairo_svg_surface_restrict_to_version (IntPtr surface, SvgVersion version);
                #endregion
 
-               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
-               internal static extern void cairo_text_extents (IntPtr cr, string text, out TextExtents extents);
+               [DllImport (cairo, CallingConvention = CallingConvention.Cdecl)]
+               internal static extern void cairo_show_text (IntPtr cr, byte[] text);
+
+               [DllImport (cairo, CallingConvention = CallingConvention.Cdecl)]
+               internal static extern void cairo_text_extents (IntPtr cr, byte[] utf8, out TextExtents extents);
+
+               [DllImport (cairo, CallingConvention = CallingConvention.Cdecl)]
+               internal static extern void cairo_show_text (IntPtr cr, ref byte utf8);
+
+               [DllImport (cairo, CallingConvention = CallingConvention.Cdecl)]
+               internal static extern void cairo_text_extents (IntPtr cr, ref byte utf8, out TextExtents extents);
 
                [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
                internal static extern void cairo_text_path (IntPtr ct, byte[] utf8);
index 3b1e4ea46c2e5d0f9953951e3c4b798d26c3a46a..369d495ba752514ea0489a492b69b9d2fa8346cb 100644 (file)
@@ -8,8 +8,38 @@ using System.Linq;
 using Crow.Cairo;
 using System.Text.RegularExpressions;
 using System.ComponentModel;
+using System.Text;
 
 namespace Crow {
+       internal struct LineSpan
+    {
+               public readonly int Start;
+               public readonly int End;
+               public readonly int EndIncludingLineBreak;
+               public int Length => End - Start;
+               public int LengthIncludingLineBreak => EndIncludingLineBreak - Start;
+               public int LineBreakLength => EndIncludingLineBreak - End;
+               public LineSpan (int start, int end, int endIncludingLineBreak) {
+                       Start = start;
+                       End = end;
+                       EndIncludingLineBreak = endIncludingLineBreak;                  
+        }
+               public LineSpan WithStartOffset (int start) => new LineSpan (Start + start, End, EndIncludingLineBreak);
+               /*public ReadOnlySpan<char> GetSubString (string str) {                 
+                       if (Start >= str.Length)
+                               return "".AsSpan();
+                       return str.Length - Start < Length ?
+                               str.AsSpan().Slice (Start, Length) :
+                               str.AsSpan().Slice (Start);
+               }
+               public ReadOnlySpan<char> GetSubStringIncludingLineBreak (string str) {
+                       if (Start >= str.Length)
+                               return "".AsSpan ();
+                       return (str.Length - Start < LengthIncludingLineBreak) ?
+                               str.AsSpan ().Slice (Start, LengthIncludingLineBreak) :
+                               str.AsSpan ().Slice (Start);
+               }*/
+       }
        public class Label : Widget
     {
                #region CTOR
@@ -28,7 +58,7 @@ namespace Crow {
         //TODO:change protected to private
 
                #region private and protected fields
-               string _text = "label";
+               string _text;
         Alignment _textAlignment;
                bool horizontalStretch;
                bool verticalStretch;
@@ -112,20 +142,14 @@ namespace Crow {
                [DefaultValue("label")]
         public string Text
         {
-            get {
-                               return lines == null ?
-                                       _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j);
-                       }
+                       get => _text;
             set
             {
-                               if (string.Equals (value, _text, StringComparison.Ordinal))
+                               if (_text.AsSpan ().SequenceEqual (value.AsSpan ()))
                     return;
 
                 _text = value;
 
-                               if (string.IsNullOrEmpty(_text))
-                                       _text = "";
-
                                lines = getLines;
 
                                OnTextChanged (this, new TextChangeEventArgs (Text));
@@ -135,7 +159,7 @@ namespace Crow {
                [DefaultValue(false)]
                public bool Selectable
                {
-                       get { return _selectable; }
+                       get => _selectable;
                        set
                        {
                                if (value == _selectable)
@@ -150,7 +174,7 @@ namespace Crow {
                [DefaultValue(false)]
                public bool Multiline
                {
-                       get { return _multiline; }
+                       get => _multiline;
                        set
                        {
                                if (value == _multiline)
@@ -198,11 +222,12 @@ namespace Crow {
                                        gr.FontOptions = Interface.FontRenderingOptions;
                                        gr.Antialias = Interface.Antialias;
                                        try {
-                                               string l = lines [_currentLine];
-                                               if (_currentCol < l.Length)
+                                               //string l = lines [_currentLine].GetSubString (_text);
+                                               ;
+                                               /*if (_currentCol < l.Length)
                                                        l = l.Remove (Math.Min (_currentCol, l.Length));
-                                               l = l.Replace ("\t", new String (' ', Interface.TAB_SIZE));
-                                               return (int)Math.Ceiling (gr.TextExtents (l).XAdvance);
+                                               l = l.Replace ("\t", new String (' ', Interface.TAB_SIZE));*/
+                                               return (int)Math.Ceiling (gr.TextExtents (_text.GetLine (lines[_currentLine], _currentCol), Interface.TAB_SIZE).XAdvance);
                                        } catch {
                                                System.Diagnostics.Debug.WriteLine ("xpos measuring fault in label");
                                                return 0;
@@ -266,12 +291,7 @@ namespace Crow {
                /// <summary>
                /// return char at CurrentLine, CurrentColumn
                /// </summary>
-               [XmlIgnore]protected Char CurrentChar
-               {
-                       get {
-                               return lines [CurrentLine][CurrentColumn];
-                       }
-               }
+               [XmlIgnore]protected Char CurrentChar => _text[lines[CurrentLine].Start + CurrentColumn];
                /// <summary>
                /// ordered selection start and end positions in char units
                /// </summary>
@@ -297,25 +317,41 @@ namespace Crow {
                                if (SelRelease < 0 || SelBegin < 0)
                                        return "";
                                if (selectionStart.Y == selectionEnd.Y)
-                                       return lines [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X);
-                               string tmp = "";
-                               tmp = lines [selectionStart.Y].Substring (selectionStart.X);
-                               for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) {
-                                       tmp += Interface.LineBreak + lines [l];
-                               }
-                               tmp += Interface.LineBreak + lines [selectionEnd.Y].Substring (0, selectionEnd.X);
-                               return tmp;
+                                       return _text.Substring (lines[selectionStart.Y].Start + selectionStart.X, selectionEnd.X - selectionStart.X);
+
+                               StringBuilder tmp = new StringBuilder (_text.GetLineIncludingLineBreak (lines[selectionStart.Y], selectionStart.X).ToString ());
+                               for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++)
+                                       tmp.Append (_text.GetLineIncludingLineBreak (lines[l]).ToString ());
+                               tmp.Append (_text.Substring (lines[selectionEnd.Y].Start, selectionEnd.X));
+                               return tmp.ToString ();
                        }
                }
                [XmlIgnore]public bool selectionIsEmpty
                { get { return SelRelease < 0; } }
 
-               List<string> lines;
-               List<string> getLines {
+               List<LineSpan> lines;
+               List<LineSpan> getLines {
                        get {
-                               return _multiline ?
-                                       Regex.Split (_text, "\r\n|\r|\n|\\\\n").ToList() :
-                                       new List<string>(new string[] { _text });
+                               if (string.IsNullOrEmpty(_text))
+                                       return new List<LineSpan> (new LineSpan[] { new LineSpan (0, 0, 0) });
+                               if (!_multiline)
+                                       return new List<LineSpan> (new LineSpan[] { new LineSpan (0, _text.Length, _text.Length) });
+                               List<LineSpan> lines = new List<LineSpan> ();
+                               bool lineBreak = false;
+                               int start = 0, end = 0;
+                for (int i = 0; i < _text.Length; i++) {
+                                       if (_text[i] == '\r' || _text[i] == '\n') {
+                                               if (lineBreak)
+                                                       continue;
+                                               lineBreak = true;
+                                               end = i;
+                    }else if (lineBreak) {
+                                               lines.Add (new LineSpan (start, end, i));
+                                               start = end = i;
+                                               lineBreak = false;
+                    }
+                }
+                               return lines;
                        }
                }
                /// <summary>
@@ -353,7 +389,7 @@ namespace Crow {
                        //skip white spaces
                        while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
                                CurrentColumn--;
-                       while (char.IsLetterOrDigit (lines [CurrentLine] [CurrentColumn]) && CurrentColumn > 0)
+                       while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0)
                                CurrentColumn--;
                        if (!char.IsLetterOrDigit (this.CurrentChar))
                                CurrentColumn++;
@@ -377,16 +413,14 @@ namespace Crow {
                                                return;
                                        CurrentLine--;
                                        CurrentColumn = lines [CurrentLine].Length;
-                                       lines [CurrentLine] += lines [CurrentLine + 1];
-                                       lines.RemoveAt (CurrentLine + 1);
 
-                                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                                       Text = _text.Remove (lines[CurrentLine].End, lines[CurrentLine].LineBreakLength);
                                        return;
                                }
                                CurrentColumn--;
-                               lines [CurrentLine] = lines [CurrentLine].Remove (CurrentColumn, 1);
+                               Text = _text.Remove (lines[CurrentLine].Start + CurrentColumn, 1);                              
                        } else {
-                               int linesToRemove = selectionEnd.Y - selectionStart.Y + 1;
+                               /*int linesToRemove = selectionEnd.Y - selectionStart.Y + 1;
                                int l = selectionStart.Y;
 
                                if (linesToRemove > 0) {
@@ -401,9 +435,9 @@ namespace Crow {
                                        lines [l] = lines [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X);
                                CurrentColumn = selectionStart.X;
                                SelBegin = -1;
-                               SelRelease = -1;
+                               SelRelease = -1;*/
                        }
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                       //OnTextChanged (this, new TextChangeEventArgs (Text));
                }
                /// <summary>
                /// Insert new string at caret position, should be sure no line break is inside.
@@ -411,7 +445,7 @@ namespace Crow {
                /// <param name="str">String.</param>
                protected void Insert(string str)
                {
-                       if (!selectionIsEmpty)
+                       /*if (!selectionIsEmpty)
                                this.DeleteChar ();
                        if (_multiline) {
                                string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray();
@@ -423,21 +457,26 @@ namespace Crow {
                                        CurrentColumn += strLines[i].Length;
                                }
                        } else {
+                               ReadOnlySpan<char> a = _text.AsSpan ().Slice (0 ,lines[CurrentLine].Start + CurrentColumn);
+                               ReadOnlySpan<char> b = _text.AsSpan ().Slice (lines[CurrentLine].Start + CurrentColumn);
+
+                               _text = string.Concat( (a, str.AsSpan(), b);
+
                                lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, str);
                                CurrentColumn += str.Length;
                        }
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                       OnTextChanged (this, new TextChangeEventArgs (Text));*/
                }
                /// <summary>
                /// Insert a line break.
                /// </summary>
                protected void InsertLineBreak()
                {
-                       lines.Insert(CurrentLine + 1, lines[CurrentLine].Substring(CurrentColumn));
+                       /*lines.Insert(CurrentLine + 1, lines[CurrentLine].Substring(CurrentColumn));
                        lines [CurrentLine] = lines [CurrentLine].Substring (0, CurrentColumn);
                        CurrentLine++;
                        CurrentColumn = 0;
-                       OnTextChanged (this, new TextChangeEventArgs (Text));
+                       OnTextChanged (this, new TextChangeEventArgs (Text));*/
                }
                bool textMeasureIsUpToDate = false;
                Size cachedTextSize = default(Size);
@@ -462,11 +501,9 @@ namespace Crow {
                                        cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent+fe.Descent) * Math.Max (1, lines.Count));
 
                                        try {
-                                               for (int i = 0; i < lines.Count; i++) {
-                                                       string l = lines[i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
-
-                                                       TextExtents tmp = gr.TextExtents (l);
-
+                                               TextExtents tmp = default;
+                                               for (int i = 0; i < lines.Count; i++) {                                                 
+                                                       gr.TextExtents (_text.GetLine (lines[i]), Interface.TAB_SIZE, out tmp);
                                                        if (tmp.XAdvance > te.XAdvance)
                                                                te = tmp;
                                                }
@@ -597,31 +634,38 @@ namespace Crow {
                        #endregion
 
                        //****** debug selection *************
-//                     if (SelRelease >= 0) {
-//                             new SolidColor(Color.DarkGreen).SetAsSource(gr);
-//                             Rectangle R = new Rectangle (
-//                                                  rText.X + (int)SelEndCursorPos - 3,
-//                                                  rText.Y + (int)(SelRelease.Y * (fe.Ascent+fe.Descent)),
-//                                                  6,
-//                                                  (int)(fe.Ascent+fe.Descent));
-//                             gr.Rectangle (R);
-//                             gr.Fill ();
-//                     }
-//                     if (SelBegin >= 0) {
-//                             new SolidColor(Color.DarkRed).SetAsSource(gr);
-//                             Rectangle R = new Rectangle (
-//                                     rText.X + (int)SelStartCursorPos - 3,
-//                                     rText.Y + (int)(SelBegin.Y * (fe.Ascent+fe.Descent)),
-//                                     6,
-//                                     (int)(fe.Ascent+fe.Descent));
-//                             gr.Rectangle (R);
-//                             gr.Fill ();
-//                     }
+                       //                      if (SelRelease >= 0) {
+                       //                              new SolidColor(Color.DarkGreen).SetAsSource(gr);
+                       //                              Rectangle R = new Rectangle (
+                       //                                                   rText.X + (int)SelEndCursorPos - 3,
+                       //                                                   rText.Y + (int)(SelRelease.Y * (fe.Ascent+fe.Descent)),
+                       //                                                   6,
+                       //                                                   (int)(fe.Ascent+fe.Descent));
+                       //                              gr.Rectangle (R);
+                       //                              gr.Fill ();
+                       //                      }
+                       //                      if (SelBegin >= 0) {
+                       //                              new SolidColor(Color.DarkRed).SetAsSource(gr);
+                       //                              Rectangle R = new Rectangle (
+                       //                                      rText.X + (int)SelStartCursorPos - 3,
+                       //                                      rText.Y + (int)(SelBegin.Y * (fe.Ascent+fe.Descent)),
+                       //                                      6,
+                       //                                      (int)(fe.Ascent+fe.Descent));
+                       //                              gr.Rectangle (R);
+                       //                              gr.Fill ();
+                       //                      }
                        //*******************
-
+                       if (string.IsNullOrEmpty (_text)) {
+                               gr.Restore ();
+                               return;
+                       }
                        for (int i = 0; i < lines.Count; i++) {
-                               string l = lines [i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
-                               int lineLength = (int)gr.TextExtents (l).XAdvance;
+                               if (lines[i].Length == 0)
+                                       continue;
+                               ReadOnlySpan<char> chars = _text.GetLine (lines[i]);
+
+                               //string l = lines [i].Replace ("\t", new String (' ', Interface.TAB_SIZE));
+                               int lineLength = (int)gr.TextExtents (chars, Interface.TAB_SIZE).XAdvance;
                                Rectangle lineRect = new Rectangle (
                                        rText.X,
                                        rText.Y + i * (int)(fe.Ascent+fe.Descent),
@@ -636,13 +680,11 @@ namespace Crow {
 //                                     TextAlignment == Alignment.TopRight ||
 //                                     TextAlignment == Alignment.BottomRight)
 //                                     lineRect.X += (rText.Width - lineLength);
-                               if (string.IsNullOrWhiteSpace (l))
-                                       continue;
 
                                Foreground.SetAsSource (IFace, gr);
                                gr.MoveTo (lineRect.X,(double)rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i) ;
 
-                gr.ShowText (l);
+                gr.ShowText (chars, Interface.TAB_SIZE);
                                gr.Fill ();
 
                                if (Selectable) {
@@ -672,7 +714,7 @@ namespace Crow {
                                                gr.Clip ();
                                                gr.SetSource (SelectionForeground);
                                                gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i);
-                                               gr.ShowText (l);
+                                               gr.ShowText (chars, Interface.TAB_SIZE);
                                                gr.Fill ();
                                                gr.Restore ();
                                        }
@@ -774,27 +816,31 @@ namespace Crow {
                        double cPos = 0f;
 
                        CurrentLine = (int)(mouseLocalPos.Y / (fe.Ascent+fe.Descent));
-
+                       
                        //fix cu
                        if (CurrentLine >= lines.Count)
                                CurrentLine = lines.Count - 1;
 
+                       LineSpan ls = lines[CurrentLine];
+                       ReadOnlySpan<char> curLine = _text.GetLine (lines[CurrentLine]);
+
                        switch (TextAlignment) {
                        case Alignment.Center:
                        case Alignment.Top:
                        case Alignment.Bottom:
-                               cPos+= ClientRectangle.Width - gr.TextExtents(lines [CurrentLine]).Width/2.0;
+                               cPos += ClientRectangle.Width - gr.TextExtents (curLine, Interface.TAB_SIZE).Width / 2.0;
                                break;
                        case Alignment.Right:
                        case Alignment.TopRight:
                        case Alignment.BottomRight:
-                               cPos += ClientRectangle.Width - gr.TextExtents(lines [CurrentLine]).Width;
+                               cPos += ClientRectangle.Width - gr.TextExtents (curLine, Interface.TAB_SIZE).Width;
                                break;
                        }
 
+                       
                        for (int i = 0; i < lines[CurrentLine].Length; i++)
                        {
-                               string c = lines [CurrentLine].Substring (i, 1);
+                               /*string c = .Substring (i, 1);
                                if (c == "\t")
                                        c = new string (' ', Interface.TAB_SIZE);
 
@@ -810,7 +856,7 @@ namespace Crow {
                                        return;
                                }
 
-                               cPos += te.XAdvance;
+                               cPos += te.XAdvance;*/
                        }
                        CurrentColumn = lines[CurrentLine].Length;
                        textCursorPos = cPos;
@@ -831,9 +877,9 @@ namespace Crow {
                double GetXFromTextPointer(Context gr, Point pos)
                {
                        try {
-                               string l = lines [pos.Y].Substring (0, pos.X).
-                                       Replace ("\t", new String (' ', Interface.TAB_SIZE));
-                               return gr.TextExtents (l).XAdvance;
+                               /*string l = lines [pos.Y].Substring (0, pos.X).
+                                       Replace ("\t", new String (' ', Interface.TAB_SIZE));*/
+                               return gr.TextExtents (_text.GetLine(lines[pos.Y], pos.X), Interface.TAB_SIZE).XAdvance;
                        } catch{
                                return -1;
                        }
diff --git a/Samples/PerfTests/Properties/launchSettings.json b/Samples/PerfTests/Properties/launchSettings.json
new file mode 100644 (file)
index 0000000..2ffae32
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "profiles": {
+    "PerfTests": {
+      "commandName": "Project",
+      "commandLineArgs": "1"
+    }
+  }
+}
\ No newline at end of file