public Paragraph(int index, float maxWidth) { Index = index; Top = index; BreakWidth = maxWidth; m_Glyphs = new GlyphList(); m_Breaks = new BreakList(); }
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; } }