Ejemplo n.º 1
0
        public static float LineWidth(this Paragraph para, int lineIndex)
        {
            if (para.Breaks.Count == 0)
            {
                return(para.Glyphs.Sum(gx => gx.Width));
            }
            BreakList.Node n = para.Breaks.Head.Skip(lineIndex - 1);
            if (n == null)
            {
                return(0);
            }
            GlyphList.Node g   = para.Glyphs.Head;
            int            idx = n.Value;

            g = g.Skip(idx);
            n = n.Next;
            float w = 0;

            while (g != null && (n == null || idx++ < n.Value))
            {
                w += g.Value.Width;
                g  = g.Next;
            }
            return(w);
        }
Ejemplo n.º 2
0
        public static IEnumerable <float> LineWidths(this Paragraph para)
        {
            if (para.Breaks.Count == 0)
            {
                yield return(para.Glyphs.Sum(g => g.Width));
            }
            else
            {
                BreakList.Node n = para.Breaks.Head;
                GlyphList.Node g = para.Glyphs.Head;
                float          w = 0;
                int            i = 0;
                while (n != null)
                {
                    while (g != null && ++i <= n.Value)
                    {
                        w += g.Value.Width;
                        g  = g.Next;
                    }
                    i--;
                    yield return(w);

                    n = n.Next;
                    w = 0;
                }

                while (g != null)
                {
                    w += g.Value.Width;
                    g  = g.Next;
                }
                yield return(w);
            }
        }
 public void MoveEndOfWord()
 {
     GlyphList.Node n = CurrentParagraph.Glyphs.Head.Skip(CursorPosition);
     while (n != null && !Paragraph.IsSpaceWrapCharacter(n.Value.Char))
     {
         n = n.Next;
         CursorPosition++;
     }
 }
Ejemplo n.º 4
0
        // used for cursor placement
        public static ParagraphPosition PositionAtLineWidth(this Paragraph para, float width, int line)
        {
            if (para.Glyphs == null || para.Glyphs.Count == 0 || line < 0 || line >= para.LineCount)
            {
                return(ParagraphPosition.Empty);
            }
            GlyphList.Node ng         = para.Glyphs.Head;
            int            breakIndex = -1;

            BreakList.Node nb = para.Breaks.Head;
            if (nb != null)
            {
                breakIndex = nb.Value;
            }
            int   i     = 0;
            float w     = 0;
            float whalf = (int)(ng.Value.Width / 2f + 0.5f);
            int   x     = 0;
            int   y     = 0;

            while ((y < line || (w + whalf <= width)) && ng.Next != null)
            {
                if (i == breakIndex - 1)
                {
                    if (y >= line)
                    {
                        return(new ParagraphPosition(i, x, y, w.Ceil(), ng.Value.Width));
                    }

                    w     = 0;
                    whalf = (int)(ng.Value.Width / 2f + 0.5f);
                    x     = 0;
                    y++;
                    nb = nb.Next;
                    if (nb != null)
                    {
                        breakIndex = nb.Value;
                    }
                }
                else
                {
                    x++;
                    w    += ng.Value.Width;
                    whalf = (int)(ng.Value.Width / 2f + 0.5f);
                }

                ng = ng.Next;
                i++;
            }
            return(new ParagraphPosition(i, x, y, w.Ceil(), ng.Value.Width));
        }
        public void MoveNextWord()
        {
            bool loopFirst = true;

            if (CursorPosition >= CurrentParagraph.Length - 1)
            {
                if (CurrentParagraphIndex < Paragraphs.Count - 1)
                {
                    MoveNextChar();
                    while (CurrentParagraph.Length <= 1)
                    {
                        MoveNextChar();
                    }
                    loopFirst = false;
                }
            }

            GlyphList.Node n = CurrentParagraph.Glyphs.Head;
            int            k = CursorPosition;

            if (loopFirst)
            {
                for (int i = 0; i < CursorPosition; i++)
                {
                    n = n.Next;
                }
                k = CursorPosition;
                while (n != null && n.Value.Char != ' ')
                {
                    n = n.Next;
                    k++;
                }
            }

            while (n != null && n.Value.Char == ' ')
            {
                n = n.Next;
                k++;
            }
            if (k < CurrentParagraph.Length - 1)
            {
                CursorPosition = k;
            }
            else
            {
                CursorPosition = CurrentParagraph.Length - 1;
            }

            ResetCursorColoumns();
        }
        public virtual void MovePrevWord()
        {
            if (CursorPosition == 0)
            {
                if (CurrentParagraphIndex > 0)
                {
                    MovePrevChar();
                    while (CurrentParagraph.Length <= 1)
                    {
                        MovePrevChar();
                    }
                    if (CursorPosition > 0)
                    {
                        CursorPosition--;
                    }
                    while (CurrentParagraph.Glyphs [CursorPosition].Char == ' ' && CursorPosition > 0)
                    {
                        CursorPosition--;
                    }
                    CursorPosition++;
                }
                ResetCursorColoumns();
                return;
            }

            GlyphList.Node n = CurrentParagraph.Glyphs.Head;
            int            i = 0;
            int            k = 0;

            bool spaceFlag = false;

            while (k != CursorPosition && n != null)
            {
                if (n.Value.Char == ' ')
                {
                    spaceFlag = true;
                }
                else if (spaceFlag)
                {
                    i         = k;
                    spaceFlag = false;
                }

                n = n.Next;
                k++;
            }

            CursorPosition = i;
            ResetCursorColoumns();
        }
Ejemplo n.º 7
0
        // used for general purpose
        public static ParagraphPosition PositionAtIndex(this Paragraph para, int pos)
        {
            if (para.Glyphs == null || para.Glyphs.Count == 0 || pos <= 0)
            {
                return(ParagraphPosition.Empty);
            }
            pos = pos.Clamp(0, para.Glyphs.Count - 1);
            GlyphList.Node ng         = para.Glyphs.Head;
            int            breakIndex = -1;

            BreakList.Node nb = para.Breaks.Head;
            if (nb != null)
            {
                breakIndex = nb.Value;
            }
            int i = 0;
            int x = 0;
            int w = 0;
            int y = 0;

            while (i < pos && ng.Next != null)
            {
                if (i == breakIndex - 1)
                {
                    w = 0;
                    x = 0;
                    y++;
                    nb = nb.Next;
                    if (nb != null)
                    {
                        breakIndex = nb.Value;
                    }
                }
                else
                {
                    x++;
                    w += ng.Value.Width;
                }

                i++;
                ng = ng.Next;
            }
            return(new ParagraphPosition(pos, x, y, w, ng.Value.Width));
        }
        public void InsertLineBreak()
        {
            if (CursorPosition >= CurrentParagraph.Length - 1)
            {
                if (CurrentParagraphIndex >= Paragraphs.Count - 1)
                {
                    // most common case: Writing at the edge
                    Paragraphs.AddLast(new Paragraph(Paragraphs.Count, BreakWidth, String.Empty, Font, Flags));
                    MoveNextChar();
                }
                else
                {
                    MoveNextChar();
                    Paragraph current = CurrentParagraph;
                    Paragraph para    = new Paragraph(CurrentParagraphIndex, BreakWidth, "\n", Font, Flags);
                    para.LineOffset = current.LineOffset;
                    para.Height     = LineHeight;
                    Paragraphs.Insert(CurrentParagraphIndex, para);
                    //current = CurrentParagraph;
                }
            }
            else if (CursorPosition == 0)
            {
                Paragraph current = CurrentParagraph;
                Paragraph para    = new Paragraph(CurrentParagraphIndex, BreakWidth, "\n", Font, Flags);
                para.LineOffset = current.LineOffset;
                para.Height     = LineHeight;
                para.Top        = current.Top;
                Paragraphs.Insert(CurrentParagraphIndex, para);
                CurrentParagraphIndex++;
            }
            else
            {
                Paragraph      para = new Paragraph(CurrentParagraphIndex + 1, BreakWidth);
                Paragraph      cp   = CurrentParagraph;
                GlyphList.Node np   = cp.Glyphs.Head;
                for (int i = 0; i < CursorPosition - 1; i++)
                {
                    np = np.Next;
                }
                GlyphList.Node npTail = np;

                np = np.Next;
                while (np != null)
                {
                    para.Glyphs.AddLast(np.Value);
                    np = np.Next;
                }
                para.NeedsWordWrap = true;

                // cut np..
                npTail.Next = null;
                cp.Glyphs.ResetCurrent();
                cp.AppendChar('\n', Font, Flags);
                Paragraphs.Insert(++CurrentParagraphIndex, para);
            }

            CurrentParagraphIndex = CurrentParagraphIndex.Clamp(0, Paragraphs.Count - 1);
            CursorPosition        = 0;
            ResetCursorColoumns();
            //Paragraphs.OnUpdateAsync (CurrentParagraphIndex - 1, BreakWidth);
            Paragraphs.OnUpdate(CurrentParagraphIndex - 1, BreakWidth, false, 250);
        }
Ejemplo n.º 9
0
        public void WordWrap(float breakWidth)
        {
            // ToDo: Still not perfect:
            // * Lines with ending NewLine may hang over
            // (the non-printable NewLine character is right above breakwidth)
            // * Lines without any break-chars may hang one character over breakwidth

            lock (SyncObject) {
                if (!NeedsWordWrap && BreakWidth == breakWidth)
                {
                    return;
                }

                BreakWidth    = breakWidth;
                NeedsWordWrap = false;

                // Since here, we completely work with temporary local variables
                // and set final values once finished.

                GlyphList.Node curr       = Glyphs.Head;
                GlyphList.Node prev       = curr;
                BreakList      lineBreaks = new BreakList();

                float currentWidth = 0;
                float totalWidth   = 0;
                float maxWidth     = 0;

                int pos = 0;
                int prevBreakCharPos = 0;

                while (curr != null)
                {
                    currentWidth += curr.Value.Width;
                    totalWidth   += currentWidth;

                    if (currentWidth > BreakWidth && curr.Next != null)
                    {
                        if (prevBreakCharPos == 0)
                        {
                            lineBreaks.AddLast(pos);
                            currentWidth = curr.Value.Width;
                            prev         = curr;
                        }
                        else
                        {
                            lineBreaks.AddLast(prevBreakCharPos);
                            prevBreakCharPos = 0;
                            currentWidth     = 0;
                            while (prev != curr)
                            {
                                currentWidth += prev.Value.Width;
                                prev          = prev.Next;
                            }
                        }
                    }
                    else if (IsSpaceWrapCharacter(curr.Value.Char) || (IsWrapCharacter(curr.Value.Char) && curr.Next != null && !IsSpaceWrapCharacter(curr.Next.Value.Char)))
                    {
                        prevBreakCharPos = pos + 1;
                        prev             = curr;
                    }

                    maxWidth = Math.Max(maxWidth, currentWidth);
                    curr     = curr.Next;
                    pos++;
                }

                // Update final values
                Concurrency.LockFreeUpdate(ref m_Breaks, lineBreaks);
                Width           = maxWidth.Ceil();
                TotalGlyphWidth = totalWidth;
            }
        }