private void IterateString(string text, Vector2 position, bool draw, float scale, Color4 color, CoordinateType coordinateType, out StringMetrics metrics) { metrics = new StringMetrics(); float scalY = coordinateType == CoordinateType.SNorm ? -1 : 1; var visualText = NBidi.NBidi.LogicalToVisual(text); var codePoints = Helpers.ConvertToCodePointArray(visualText); for (var i = 0; i < codePoints.Length; i++) { var c = codePoints[i]; var charDesc = GetCharDescription(c); var charMetrics = charDesc.ToStringMetrics(position, scale, scale * scalY); if (draw) { if (charMetrics.FullRectSize.X != 0 && charMetrics.FullRectSize.Y != 0) { var posY = position.Y - scalY * charMetrics.OverhangTop; var posX = position.X - charMetrics.OverhangLeft; Sprite.Draw(charDesc.TableDescription.Srv, new Vector2(posX, posY), charMetrics.FullRectSize, Vector2.Zero, 0, charDesc.TexCoordsStart, charDesc.TexCoordsSize, color, coordinateType); } } metrics.Merge(charMetrics); position.X += charMetrics.Size.X; // Break newlines if (c == '\r') { position.X = metrics.TopLeft.X; } if (c == '\n') { position.Y = metrics.BottomRight.Y - charMetrics.Size.Y / 2; } } }
/// <summary> /// Draws the string in the specified coordinate system aligned in the given rectangle. The text is not clipped or wrapped. /// </summary> /// <param name="text">The text to draw</param> /// <param name="rect">The rectangle in which to align the text</param> /// <param name="align">Alignment of text in rectangle</param> /// <param name="realFontSize">The real font size in the chosen coordinate system</param> /// <param name="color">The color in which to draw the text</param> /// <param name="coordinateType">The chosen coordinate system</param> /// <returns>The StringMetrics for the rendered text</returns> public StringMetrics DrawString(string text, RectangleF rect, TextAlignment align, float realFontSize, Color4 color, CoordinateType coordinateType) { // If text is aligned top and left, no adjustment has to be made if (align.HasFlag(TextAlignment.Top) && align.HasFlag(TextAlignment.Left)) { return(DrawString(text, new Vector2(rect.X, rect.Y), realFontSize, color, coordinateType)); } text = text.Replace("\r", ""); var rawTextMetrics = MeasureString(text, realFontSize, coordinateType); var mMetrics = MeasureString("m", realFontSize, coordinateType); float startY; if (align.HasFlag(TextAlignment.Top)) { startY = rect.Top; } else if (align.HasFlag(TextAlignment.VerticalCenter)) { startY = rect.Top + rect.Height / 2 - rawTextMetrics.Size.Y / 2; } else { startY = rect.Bottom - rawTextMetrics.Size.Y; } var totalMetrics = new StringMetrics(); // break text into lines var lines = text.Split('\n'); for (var i = 0; i < lines.Length; i++) { var line = lines[i]; float startX; if (align.HasFlag(TextAlignment.Left)) { startX = rect.X; } else { var lineMetrics = MeasureString(line, realFontSize, coordinateType); startX = align.HasFlag(TextAlignment.HorizontalCenter) ? rect.X + rect.Width / 2 - lineMetrics.Size.X / 2 : rect.Right - lineMetrics.Size.X; } { var lineMetrics = DrawString(line, new Vector2(startX, startY), realFontSize, color, coordinateType); startY += mMetrics.Size.Y < 0 ? Math.Min(lineMetrics.Size.Y, mMetrics.Size.Y) : Math.Max(lineMetrics.Size.Y, mMetrics.Size.Y); totalMetrics.Merge(lineMetrics); } } return(totalMetrics); }
private void IterateString(string text, Vector2 position, float angle, bool draw, float scale, Color4 color, CoordinateType coordinateType, out StringMetrics metrics) { metrics = new StringMetrics(); float scalY = coordinateType == CoordinateType.SNorm ? -1 : 1; var visualText = NBidi.NBidi.LogicalToVisual(text); var codePoints = Helpers.ConvertToCodePointArray(visualText); float sine, cosine; if (angle != 0f) { sine = (float)Math.Sin(angle); cosine = (float)Math.Cos(angle); } else { sine = cosine = 0f; } var x = 0f; var y = Lazier.Create(() => Math.Abs(GetCharDescription('M').CharSize.Y *scale *scalY)); for (var i = 0; i < codePoints.Length; i++) { var c = codePoints[i]; var charDesc = GetCharDescription(c); var charMetrics = charDesc.ToStringMetrics(position, scale, scale * scalY); metrics.Merge(charMetrics); if (c != '\r' && c != '\n') { if (draw) { var h = charMetrics.FullRectSize.Y; if (h != 0 && charMetrics.FullRectSize.X != 0) { var fix = new Vector2(-charMetrics.OverhangLeft, -scalY * charMetrics.OverhangTop); if (angle != 0f) { fix = SpriteRenderer.Rotate(fix, sine, cosine); } Sprite.Draw(charDesc.TableDescription.Srv, position + fix, charMetrics.FullRectSize, Vector2.Zero, sine, cosine, charDesc.TexCoordsStart, charDesc.TexCoordsSize, color, coordinateType); } } } var delta = new Vector2(charMetrics.Size.X + KerningAdjustment, 0f); switch (c) { case '\n': delta.Y += y.Value; goto case '\r'; case '\r': delta.X = -x; x = 0f; break; default: x += delta.X; break; } if (angle != 0f) { delta = SpriteRenderer.Rotate(delta, sine, cosine); } position += delta; } }