Пример #1
0
 public LineBreaker(Renderer.RendererBase renderer, Font defaultFont)
     : base(renderer, defaultFont)
 {
     m_Formatter = new LeftFormatter(renderer, defaultFont);
 }
Пример #2
0
        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);
        }