/// <summary>
        /// Constructs render info from lines.
        /// </summary>
        /// <param name="lines"></param>
        public TextRenderInfo(ICanvas canvas, Font font,
                              float fontSize, params TextRenderLineInfo[] lines)
        {
            this.lines = lines;

            // We extract glyphs.
            List <RenderGlyphInfo> t = new List <RenderGlyphInfo>();

            for (int i = 0; i < lines.Length; i++)
            {
                TextRenderLineInfo info = lines[i];
                for (uint j = 0; j < info.GlyphCount; j++)
                {
                    RenderGlyphInfo g = info[j];
                    t.Add(info[j]);
                }
            }

            this.glyphs = t.ToArray();

            // May adjust.
            this.fullRange = new Vector2i(0, glyphs.Length - 1);
            this.canvas    = canvas;
            this.font      = font;
            this.fontSize  = fontSize;
        }
Beispiel #2
0
        /// <summary>
        /// Prepares text for rendering, with rectange where data should be rendered.
        /// </summary>
        public TextRenderInfo Prepare(ICanvas canvas, string text, float fontSize,
                                      TextOptions options, float lineSpacing, Vector2f leftBottom, Vector2f size)
        {
            // We extract information and convert them.
            bool newLineOrdinary = HasFlag(options, TextOptions.NewLineOrdinary);
            bool groupWords      = HasFlag(options, TextOptions.NotGroupWords);
            bool allowMulti      = HasFlag(options, TextOptions.AllowMulticharacters);

            if (!HasFlag(options, TextOptions.UseCanvasUnits))
            {
                // We use Y dimension, since it is primary axis for text (we want it properly aligned).
                fontSize *= canvas.CanvasInfo.CanvasUnitSize.Y / canvas.CanvasInfo.CanvasPixelSize.Y;
            }
            lineSpacing *= fontSize;

            // We go for each character.
            float lineY = leftBottom.Y + size.Y - fontSize;
            float lineX = leftBottom.X;

            // Return data.
            List <TextRenderLineInfo> lines       = new List <TextRenderLineInfo>();
            TextRenderLineInfo        currentLine = new TextRenderLineInfo(
                new Vector2f(leftBottom.X, leftBottom.X + size.X));

            for (int i = 0; i < text.Length; i++)
            {
                // We first check for out of range.
                if (lineY < leftBottom.Y)
                {
                    break;
                }

                // We select next character.
                int   advIndex = 1;
                Glyph obj      = null;

                // We find next glyph.
                if (text[i] != '\n' || newLineOrdinary)
                {
                    obj = SelectGlyph(text, i, out advIndex, allowMulti);
                }

                // We have it multiplied.
                float adv = obj.Advance;
                adv *= fontSize;

                // We check for line fit.
                if ((!newLineOrdinary && text[i] == '\n') || (lineX + adv >= leftBottom.X + size.X))
                {
                    // We go to new line.
                    lines.Add(currentLine);
                    lineY -= lineSpacing;
                    lineX  = leftBottom.X;
                    if (lineY < leftBottom.Y)
                    {
                        currentLine = null;
                        break;
                    }
                    else
                    {
                        i--;
                        currentLine = new TextRenderLineInfo(
                            new Vector2f(leftBottom.X, leftBottom.X + size.X));
                        continue;
                    }
                }

                // We advance and add it. We must carefully handle multi-char glyphs.
                for (int j = 0; j < advIndex; j++)
                {
                    // We create information.
                    RenderGlyphInfo info2 = new RenderGlyphInfo(
                        text[i + j], j == 0 ? text.Substring(i, advIndex) : string.Empty,
                        new Vector2f(lineX + j * (adv / advIndex), lineY), new Vector2f(adv / advIndex, fontSize),
                        j == 0 ? new Vector2f(adv, fontSize) : Vector2f.Zero, j == 0 ? obj : null, i + j);

                    currentLine.Append(info2);
                }

                // We advance.
                lineX += adv;
            }

            if (currentLine != null)
            {
                lines.Add(currentLine);
            }

            TextRenderInfo info = new TextRenderInfo(canvas, this, fontSize, lines.ToArray());

            // We now post-transform using flags.
            if (HasFlag(options, TextOptions.Top))
            {
                // Already positioned.
            }
            else if (HasFlag(options, TextOptions.Bottom))
            {
                float disp = lines[lines.Count - 1].Bottom - leftBottom.Y;

                info.Translate(new Vector2f(0, -disp));
            }
            else
            {
                // Center positioning.
                float disp = (lines[lines.Count - 1].Bottom - leftBottom.Y) / 2.0f;

                info.Translate(new Vector2f(0, -disp));
            }

            // We also align.
            if (HasFlag(options, TextOptions.Left))
            {
                // Already aligned.
                //info.LeftAlignLines();
            }
            else if (HasFlag(options, TextOptions.Right))
            {
                info.RightAlignLines();
            }
            else
            {
                info.CenterAlignLines();
            }

            return(info);
        }