// TODO: other preparations /// <summary> /// Prepares and renders, with rectange range. /// </summary> public TextRenderInfo Render(IFill fill, ICanvas canvas, string text, float fontSize, TextOptions options, float lineSpacing, Vector2f leftBottom, Vector2f size) { TextRenderInfo info = Prepare(canvas, text, fontSize, options, lineSpacing, leftBottom, size); info.Render(fill); return(info); }
/// <summary> /// Prepares and renders, with customized line starts and lengths. /// </summary> public TextRenderInfo Render(IFill fill, ICanvas canvas, string text, float fontSize, TextOptions optons, Vector2f[] lineStarts, float[] lineLengths) { TextRenderInfo info = Prepare(canvas, text, fontSize, optons, lineStarts, lineLengths); info.Render(fill); return(info); }
/// <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); }