/// <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; }
/// <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); }