public LineBreaker(Renderer.RendererBase renderer, Font defaultFont) : base(renderer, defaultFont) { m_Formatter = new LeftFormatter(renderer, defaultFont); }
private List <TextBlock> DoLineBreak(Paragraph paragraph, Formatter formatter, int width, int tolerance) { m_Paragraph = paragraph; m_TotalWidth = width; m_Tolerance = tolerance; m_Nodes = formatter.FormatParagraph(paragraph); m_Sum = new Sum(0, 0, 0); m_ActiveNodes.Clear(); m_ActiveNodes.AddLast(new BreakPoint(0, 0, 0, 0, 0, new Sum(0, 0, 0), null)); for (int index = 0; index < m_Nodes.Count; index++) { Node node = m_Nodes[index]; if (node.Type == NodeType.Box) { m_Sum.Width += node.Width; } else if (node.Type == NodeType.Glue) { if (index > 0 && m_Nodes[index - 1].Type == NodeType.Box) { MainLoop(index); } m_Sum.Width += node.Width; m_Sum.Stretch += ((GlueNode)node).Stretch; m_Sum.Shrink += ((GlueNode)node).Shrink; } else if (node.Type == NodeType.Penalty && ((PenaltyNode)node).Penalty != Infinity) { MainLoop(index); } } if (m_ActiveNodes.Count != 0) { LinkedListNode <BreakPoint> node = m_ActiveNodes.First; LinkedListNode <BreakPoint> tmp = null; while (node != null) { if (tmp == null || node.Value.Demerits < tmp.Value.Demerits) { tmp = node; } node = node.Next; } List <Break> breaks = new List <Break>(); while (tmp != null) { breaks.Add(new Break(tmp.Value.Position, tmp.Value.Ratio)); tmp = tmp.Value.Previous; } // breaks.Reverse(); int lineStart = 0; int y = 0; int x = 0; StringBuilder str = new StringBuilder(1000); List <TextBlock> textBlocks = new List <TextBlock>(); for (int i = breaks.Count - 2; i >= 0; i--) { int position = breaks[i].Position; float r = breaks[i].Ratio; for (int j = lineStart; j < m_Nodes.Count; j++) { if (m_Nodes[j].Type == NodeType.Box || (m_Nodes[j].Type == NodeType.Penalty && ((PenaltyNode)m_Nodes[j]).Penalty == -Infinity)) { lineStart = j; break; } } int height = 0; int baseline = 0; for (int nodeIndex = lineStart; nodeIndex <= position; nodeIndex++) { if (m_Nodes[nodeIndex].Type == NodeType.Box) { height = Math.Max(height, ((BoxNode)m_Nodes[nodeIndex]).Height); baseline = Math.Max(baseline, (int)((TextPart)((BoxNode)m_Nodes[nodeIndex]).Part).Font.FontMetrics.Baseline); } } Part part = ((BoxNode)m_Nodes[lineStart]).Part; int blockStart = lineStart; for (int nodeIndex = lineStart; nodeIndex <= position; nodeIndex++) { if ((m_Nodes[nodeIndex].Type == NodeType.Box && ((BoxNode)m_Nodes[nodeIndex]).Part != part) || nodeIndex == position) { TextBlock textBlock = new TextBlock(); textBlock.Part = part; str.Clear(); for (int k = blockStart; k < (nodeIndex - 1); k++) { if (m_Nodes[k].Type == NodeType.Glue) { if (m_Nodes[k].Width > 0) { str.Append(' '); } } else if (m_Nodes[k].Type == NodeType.Box) { str.Append(((BoxNode)m_Nodes[k]).Value); } } textBlock.Position = new Point(x, y + baseline - (int)((TextPart)part).Font.FontMetrics.Baseline); textBlock.Text = str.ToString(); textBlock.Size = new Size(formatter.MeasureText(((TextPart)part).Font, textBlock.Text).Width, height); x += textBlock.Size.Width; textBlocks.Add(textBlock); if (m_Nodes[nodeIndex].Type == NodeType.Box) { part = ((BoxNode)m_Nodes[nodeIndex]).Part; } blockStart = nodeIndex; } } x = 0; y += height; lineStart = position; } return(textBlocks); } return(null); }