const int minextra = 31; // minimum extra space to reserve /// <summary> /// This will reserve some extra free space for fast subsequent appends /// </summary> /// <returns><c>true</c>, if char was appended, <c>false</c> otherwise.</returns> /// <param name="c">The character to append</param> /// <param name="font">Font.</param> /// <param name="flags">Flags.</param> public int Append(char c, IGUIFont font, SpecialCharacterFlags flags = SpecialCharacterFlags.None) { if (c == '\r' || font == null) { return(0); } GlyphChar g = font.GetGlyph(c, flags); if (g.Glyph > 0) { try { int idx = 0; if (Length == 0) { m_Glyphs = new GlyphChar[++Length]; } else { idx = Length++; if (idx >= m_Glyphs.Length) { Array.Resize(ref m_Glyphs, idx + Math.Max(minextra, Length / 3)); } } Glyphs[idx] = g; Width += g.Width; return(1); } catch (Exception ex) { ex.LogError(); } } return(0); }
public void ParseString(string line, IGUIFont font, SpecialCharacterFlags flags) { if (font == null) { this.LogError("ParseString: font must not be null"); return; } if (line != null) { for (int i = 0; i < line.Length; i++) { char c = line [i]; if (c != '\n') { AppendChar(c, font, flags); } } } // Ensure that we end up with a line-break, no matter what the string is AppendChar('\n', font, flags); if (BreakWidth > font.Height * 2) { WordWrap(); } }
public void ParseString(string text, IGUIFont font, SpecialCharacterFlags flags = SpecialCharacterFlags.None) { Length = 0; GlyphChar[] tmp = null; if (!String.IsNullOrEmpty(text) && font != null) { tmp = new GlyphChar[text.Length]; int w = 0; for (int i = 0; i < text.Length; i++) { GlyphChar g = font.GetGlyph(text [i], flags); w += g.Width; tmp [i] = g; } Width = w; Length = text.Length; } if (tmp == null) { tmp = new GlyphChar[0]; } if (m_Glyphs == null) // called from constructor { m_Glyphs = tmp; } else { Concurrency.LockFreeUpdate(ref m_Glyphs, tmp); } }
public int Insert(int index, string text, IGUIFont font, SpecialCharacterFlags flags = SpecialCharacterFlags.None) { if (String.IsNullOrEmpty(text)) { return(0); } // we must handle 3 cases: // (1) insert at index 0, same implementation as (2) would lead to array-copy errors // (2) insert in the middle // (3) append at the end, same as with (1) if (index >= Length) { return(Append(text, font, flags)); } List <GlyphChar> glyphs = new List <GlyphChar> (text.Length); for (int i = 0; i < text.Length; i++) { GlyphChar g = font.GetGlyph(text [i], flags); if (g.Glyph != 0) { glyphs.Add(g); } } if (glyphs.Count == 0) { return(0); } GlyphChar[] source = glyphs.ToArray(); int sourceLen = source.Length; int newLen = Glyphs.Length + sourceLen + 1; GlyphChar[] arr = new GlyphChar[newLen]; if (index <= 0) { Array.Copy(source, arr, sourceLen); Array.Copy(Glyphs, 0, arr, sourceLen, Length); } else { Array.Copy(Glyphs, 0, arr, 0, index); Array.Copy(source, index, arr, 0, sourceLen); Array.Copy(Glyphs, index + sourceLen, arr, index, Length - index); } Length += sourceLen; Width += source.Sum(p => p.Width); return(sourceLen); }
public int Append(string text, IGUIFont font, SpecialCharacterFlags flags = SpecialCharacterFlags.None) { int result = 0; for (int i = 0; i < text.Length; i++) { result += Append(text [i], font, flags); } return(result); }
public void RefreshGlyphs(IGUIFont font, SpecialCharacterFlags flags) { GlyphList glyphs = new GlyphList(); foreach (GlyphChar g in Glyphs) { glyphs.AddLast(font.GetGlyph(g.Char, flags)); } Concurrency.LockFreeUpdate(ref m_Glyphs, glyphs); NeedsWordWrap = true; }
public MultiLineTextManager(MultiLineTextBox owner, SpecialCharacterFlags flags) { Owner = owner; Font = Owner.Font; Flags = flags; LineHeight = (int)Font.LineHeight; m_Paragraphs = new ParagraphList(LineHeight, BreakWidth); Paragraph para = new Paragraph(0, BreakWidth, String.Empty, Font, Flags); Paragraphs.AddLast(para); }
public int Insert(int index, char c, IGUIFont font, SpecialCharacterFlags flags = SpecialCharacterFlags.None) { if (c == '\r' || font == null) { return(0); } // we must handle 3 cases: // (1) insert at index 0, same implementation as (2) would lead to array-copy errors // (2) insert in the middle // (3) append at the end, same as with (1) if (index >= Length) { return(Append(c, font, flags)); } // first see, if we get a valid Glyph GlyphChar glyph = font.GetGlyph(c, flags); if (glyph.Glyph == 0) { return(0); } int newLen = Glyphs.Length; if (Length + 1 >= newLen) { newLen += minextra; } GlyphChar[] arr = new GlyphChar[newLen]; if (index <= 0) { Array.Copy(Glyphs, arr, 1); Glyphs [0] = glyph; } else { Array.Copy(Glyphs, 0, arr, 0, index); Glyphs [index] = glyph; Array.Copy(Glyphs, index + 1, arr, index, Length - index); } Length++; Width += glyph.Width; return(1); }
public bool InsertChar(int pos, char c, IGUIFont font, SpecialCharacterFlags flags) { GlyphChar g = font.GetGlyph(c, flags); if (g.Glyph > 0) { try { Glyphs.InsertAt(pos, g); NeedsWordWrap = true; return(true); } catch (Exception ex) { ex.LogError(); } } return(false); }
public bool AppendChar(char c, IGUIFont font, SpecialCharacterFlags flags) { GlyphChar g = font.GetGlyph(c, flags); if (g.Glyph > 0) { try { Glyphs.AddLast(g); NeedsWordWrap = true; return(true); } catch (Exception ex) { ex.LogError(); } } return(false); }
public int RemoveRange(int start, int len, IGUIFont font, SpecialCharacterFlags flags) { lock (SyncObject) { try { int count = Glyphs.RemoveRange(start, len); if (count > 0) { if (Glyphs.Count > 0 && Glyphs.Last.Char != '\n') { AppendChar('\n', font, flags); count -= 1; } NeedsWordWrap = true; WordWrap(); } return(count); } catch (Exception ex) { ex.LogError(); return(-1); } } }
public void OnRefreshGlyphsAsync(IGUIFont font, SpecialCharacterFlags flags, int lineHeight, float breakWidth) { if (AsyncScalingWordWrapResult != null && !(AsyncScalingWordWrapResult.IsCompleted || AsyncScalingWordWrapResult.CompletedSynchronously)) { if (TokenScalingWordWrapSource != null && !TokenScalingWordWrapSource.IsCancellationRequested) { TokenScalingWordWrapSource.Cancel(); } } LineHeight = lineHeight; RepeatAsyncUpdateWidth = breakWidth; // this.LogDebug ("Word-Break Job #{0} started (scaling).", count++); try { TokenScalingWordWrapSource = new CancellationTokenSource(); AsyncScalingWordWrapResult = Task.Factory.StartNew(() => this.ForEach(p => p.RefreshGlyphs(font, flags)), TokenScalingWordWrapSource.Token) .ContinueWith((t) => { if (!t.IsCanceled) { OnUpdate(0, RepeatAsyncUpdateWidth, true); } }) .ContinueWith((t) => { if (!t.IsCanceled) { OnUpdateCompleted(); } AsyncScalingWordWrapResult = null; }); } catch (Exception ex) { ex.LogError(); } }
public GlyphChar GetGlyph(char c, SpecialCharacterFlags flags) { lock (SyncObject) { char g = c; switch (c) { case ' ': if (flags.HasFlag(SpecialCharacterFlags.WhiteSpace)) { g = SpecialCharacters.SpaceDot; } break; case '\n': if (flags.HasFlag(SpecialCharacterFlags.LineBreaks)) { g = SpecialCharacters.Paragraph; } break; case '\r': return(GlyphChar.Empty); } try { GlyphInfo gi; if (GetGlyphIndex(g, out gi)) { return(new GlyphChar(c, (uint)gi.ListID, gi.Width)); } } catch (Exception ex) { ex.LogError(); } return(GlyphChar.Empty); } }
public Paragraph(int index, float maxWidth, string text, IGUIFont font, SpecialCharacterFlags flags) : this(index, maxWidth) { this.ParseString(text, font, flags); }
/// <summary> /// This will create an optimal short array without extra space /// </summary> /// <param name="source">Source.</param> /// <param name="font">Font.</param> /// <param name="flags">Flags.</param> public GlyphString(string source, IGUIFont font, SpecialCharacterFlags flags = SpecialCharacterFlags.None) { ParseString(source, font, flags); }