Пример #1
0
        public void Build()
        {
            if (!_isDirty || _text == null || _font == null)
            {
                return;
            }

            if (_vbuffer == null)
            {
                _vbuffer = new VertexBuffer(VertexFormat.PositionColorUV);
            }
            if (_ibuffer == null)
            {
                _ibuffer = new IndexBuffer();
            }

            var     i     = 0;
            TextRun run   = null;
            var     lines = new List <List <TextRun> >();
            var     line  = new List <TextRun>();

            //var nestedRuns = new Stack<TextRun>();
            //var nestedTags = new Stack<string>();
            lines.Add(line);
            run = new TextRun(_font, i, _kerning, _color);
            line.Add(run);

            var trim = false;

            while (i < _text.Length)
            {
                if (char.IsLowSurrogate(_text, i))
                {
                    i++;
                    continue;
                }

                if (trim)
                {
                    if (char.IsWhiteSpace(_text, i))
                    {
                        i++;
                        continue;
                    }
                    else
                    {
                        trim = false;
                    }
                }

                var c = char.ConvertToUtf32(_text, i++);
                if (c == '\n')
                {
                    run.End = i;
                    line    = new List <TextRun>();
                    lines.Add(line);
                    run = new TextRun(run, i);
                    line.Add(run);
                    continue;
                }
                else if (c < 32)
                {
                    continue;
                }

                var ch = run.Font[c];
                if (ch == null)
                {
                    ch = run.Font['?'];
                    if (ch == null)
                    {
                        ch = run.Font[' '];
                        if (ch == null)
                        {
                            continue;
                        }
                    }
                }

                run.Push(ch);
                if (_width > 0f && line.Sum(tr => tr.Width) > _width)
                {
                    int count;
                    var back = run.FindBreak(out count);
                    if (i - back <= run.Start)
                    {
                        if (line.Count > 1)
                        {
                            line.RemoveAt(line.Count - 1);
                            line = new List <TextRun>();
                            lines.Add(line);
                            line.Add(run);
                            trim = true;
                            continue;
                        }
                        else
                        {
                            back = 1;
                        }
                    }
                    i -= back - count;
                    run.Pop(back);
                    line = new List <TextRun>();
                    lines.Add(line);
                    run = new TextRun(run, i);
                    line.Add(run);
                    trim = true;
                }
            }
            run.End = i;

            _actualSize.X = lines.Max(l => l.Sum(tr => tr.Width));
            _actualSize.Y = lines.Sum(l => l.Max(tr => tr.Height) + _leading);

            var vertices = new List <float>();
            var indices  = new List <int>();
            var y        = 0f;

            for (i = lines.Count - 1; i >= 0; --i)
            {
                var tl = lines[i];
                var x  = 0f;
                if (_halign == HorizontalAlignment.Right)
                {
                    x = _width - tl.Sum(tr => tr.Width);
                }
                else if (_halign == HorizontalAlignment.Center)
                {
                    x = Mathf.Floor((_width - tl.Sum(tr => tr.Width)) / 2f);
                }

                foreach (var tr in tl)
                {
                    tr.Build(vertices, indices, new Vector3(x, y + (tr.Font.LineHeight - tr.Font.Base), 0f));
                    x += tr.Width;
                }
                y += tl.Max(tr => tr.Height) + _leading;
            }

            _vbuffer.Data = vertices.ToArray();
            _vbuffer.Commit();
            _ibuffer.Data = indices.ToArray();
            _ibuffer.Commit();

            _isDirty = false;
        }