private void IterateString(string text, STRVector position, bool draw, float scale, STRColor color, CoordinateType coordinateType, out StringMetrics metrics) { metrics = new StringMetrics(); STRVector startPosition = position; float scalY = coordinateType == SpriteTextRenderer.CoordinateType.SNorm ? -1 : 1; string visualText = NBidi.NBidi.LogicalToVisual(text); int[] codePoints = Helpers.ConvertToCodePointArray(visualText); foreach (int c in codePoints) { var charDesc = GetCharDescription(c); var charMetrics = charDesc.ToStringMetrics(position, scale, scale * scalY); if (draw) { if (charMetrics.FullRectSize.X != 0 && charMetrics.FullRectSize.Y != 0) { float posY = position.Y - scalY * charMetrics.OverhangTop; float posX = position.X - charMetrics.OverhangLeft; Sprite.Draw(charDesc.TableDescription.SRV, new STRVector(posX, posY), charMetrics.FullRectSize, STRVector.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; } } }
private void IterateString(string text, Vector2 position, bool draw, float scale, Color4 color, CoordinateType coordinateType, out StringMetrics metrics) { metrics = new StringMetrics(); Vector2 startPosition = position; float scalY = coordinateType == SpriteTextRenderer.CoordinateType.SNorm ? -1 : 1; foreach (char c in text) { var charDesc = GetCharDescription(c); var charMetrics = charDesc.ToStringMetrics(position, scale, scale * scalY); if (draw) { if (charMetrics.FullRectSize.X != 0 && charMetrics.FullRectSize.Y != 0) { float posY = position.Y - scalY * charMetrics.OverhangTop; float posX = position.X - charMetrics.OverhangLeft; Sprite.Draw(charDesc.TableDescription.SRV, new Vector2(posX, posY), charMetrics.FullRectSize, 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; } } }
private void IterateStringEm(string text, Vector2 position, bool Draw, float realFontSize, Color4 color, CoordinateType coordinateType, out StringMetrics metrics) { float scale = realFontSize / FontSize; IterateString(text, position, Draw, scale, color, coordinateType, out metrics); }
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 //Bottom { startY = rect.Bottom - rawTextMetrics.Size.Y; } var totalMetrics = new StringMetrics(); //break text into lines var lines = text.Split('\n'); foreach (var line in lines) { float startX; if (align.HasFlag(TextAlignment.Left)) { startX = rect.X; } else { var lineMetrics = MeasureString(line, realFontSize, coordinateType); if (align.HasFlag(TextAlignment.HorizontalCenter)) { startX = rect.X + rect.Width / 2 - lineMetrics.Size.X / 2; } else //Right { startX = rect.Right - lineMetrics.Size.X; } } var lineMetrics2 = DrawString(line, new Vector2(startX, startY), realFontSize, color, coordinateType); float lineHeight; if (mMetrics.Size.Y < 0) { lineHeight = Math.Min(lineMetrics2.Size.Y, mMetrics.Size.Y); } else { lineHeight = Math.Max(lineMetrics2.Size.Y, mMetrics.Size.Y); } startY += lineHeight; totalMetrics.Merge(lineMetrics2); } return(totalMetrics); }
public void Merge(StringMetrics second) { //if current instance has no values yet, take the values of the second instance if (Size.X == 0 && Size.Y == 0) { TopLeft = second.TopLeft; Size = second.Size; OverhangLeft = second.OverhangLeft; OverhangRight = second.OverhangRight; OverhangTop = second.OverhangTop; OverhangBottom = second.OverhangBottom; return; } //if second instance is not visible, do nothing if (second.FullRectSize.X == 0 && second.FullRectSize.Y == 0) { return; } //Flipped y axis means that positive y points upwards //Flipped x axis means that positive x points to the right bool xAxisFlipped = Size.X < 0; bool yAxisFlipped = Size.Y < 0; //Check, if axes of both instances point in the same direction if (this.Size.X * second.Size.X < 0) { throw new ArgumentException("The x-axis of the current instance is " + (xAxisFlipped ? "" : "not ") + "flipped. The x-axis of the second instance has to point in the same direction"); } if (this.Size.Y * second.Size.Y < 0) { throw new ArgumentException("The y-axis of the current instance is " + (yAxisFlipped ? "" : "not ") + "flipped. The y-axis of the second instance has to point in the same direction"); } //Update flipped info if it cannot be obtained from the current instance if (Size.X == 0) { xAxisFlipped = second.Size.X < 0; } if (Size.Y == 0) { yAxisFlipped = second.Size.Y < 0; } //Find the functions to determine the topmost of two values and so on Func <float, float, float> findTopMost, findBottomMost; Func <float, float, float> findLeftMost, findRightMost; if (yAxisFlipped) { findTopMost = Math.Max; findBottomMost = Math.Min; } else { findTopMost = Math.Min; findBottomMost = Math.Max; } if (xAxisFlipped) { findLeftMost = Math.Max; findRightMost = Math.Min; } else { findLeftMost = Math.Min; findRightMost = Math.Max; } //Find new textblock float top = findTopMost(this.TopLeft.Y, second.TopLeft.Y); float bottom = findBottomMost(this.TopLeft.Y + this.Size.Y, second.TopLeft.Y + second.Size.Y); float left = findLeftMost(this.TopLeft.X, second.TopLeft.X); float right = findRightMost(this.TopLeft.X + this.Size.X, second.TopLeft.X + second.Size.X); //Find new overhangs float topOverhangPos = findTopMost(this.FullRectTopLeft.Y, second.FullRectTopLeft.Y); float bottomOverhangPos = findBottomMost(this.FullRectTopLeft.Y + this.FullRectSize.Y, second.FullRectTopLeft.Y + second.FullRectSize.Y); float leftOverhangPos = findLeftMost(this.FullRectTopLeft.X, second.FullRectTopLeft.X); float rightOverhangPos = findRightMost(this.FullRectTopLeft.X + this.FullRectSize.X, second.FullRectTopLeft.X + second.FullRectSize.X); TopLeft = new Vector2(left, top); Size = new Vector2(right - left, bottom - top); OverhangLeft = (left - leftOverhangPos) * (xAxisFlipped ? -1 : 1); OverhangRight = (rightOverhangPos - right) * (xAxisFlipped ? -1 : 1); OverhangTop = (top - topOverhangPos) * (yAxisFlipped ? -1 : 1); OverhangBottom = (bottomOverhangPos - bottom) * (yAxisFlipped ? -1 : 1); }