/// <summary> /// Draws the string in the specified coordinate system. /// </summary> /// <param name="text">The text to draw</param> /// <param name="position">A position in the chosen coordinate system where the top left corner of the first character will be</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> protected internal StringMetrics DrawString(string text, STRVector position, float realFontSize, STRColor color, CoordinateType coordinateType) { StringMetrics sm; IterateStringEm(text, position, true, realFontSize, color, coordinateType, out sm); return(sm); }
internal StringMetrics ToStringMetrics(STRVector position, float scalX, float scalY) { return(new StringMetrics { TopLeft = position, Size = new STRVector(CharSize.X * scalX, CharSize.Y * scalY), OverhangTop = Math.Abs(scalY) * OverhangTop, OverhangBottom = Math.Abs(scalY) * OverhangBottom, OverhangLeft = Math.Abs(scalX) * OverhangLeft, OverhangRight = Math.Abs(scalX) * OverhangRight, }); }
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 STRVector ConvertCoordinate(STRVector coordinate, CoordinateType coordinateType) { switch (coordinateType) { case CoordinateType.SNorm: return(coordinate); case CoordinateType.UNorm: coordinate.X = (coordinate.X - 0.5f) * 2; coordinate.Y = -(coordinate.Y - 0.5f) * 2; return(coordinate); case CoordinateType.Relative: coordinate.X = coordinate.X / ScreenSize.X * 2 - 1; coordinate.Y = -(coordinate.Y / ScreenSize.Y * 2 - 1); return(coordinate); case SpriteTextRenderer.CoordinateType.Absolute: coordinate.X = coordinate.X / viewport.Width * 2 - 1; coordinate.Y = -(coordinate.Y / viewport.Height * 2 - 1); return(coordinate); } return(STRVector.Zero); }
private void IterateStringEm(string text, STRVector position, bool Draw, float realFontSize, STRColor color, CoordinateType coordinateType, out StringMetrics metrics) { float scale = realFontSize / _FontSize; IterateString(text, position, Draw, scale, color, coordinateType, out metrics); }
/// <summary> /// Draws the string untransformed in absolute coordinate system. /// </summary> /// <param name="text">The text to draw</param> /// <param name="position">A position in absolute coordinates where the top left corner of the first character will be</param> /// <param name="color">The color in which to draw the text</param> /// <returns>The StringMetrics for the rendered text</returns> protected internal StringMetrics DrawString(string text, STRVector position, STRColor color) { return(DrawString(text, position, FontSize, color, CoordinateType.Absolute)); }
/// <summary> /// Merges this instance of StringMetrics with another instance. /// The textblock and overhangs of this instance will be increased to cover both instances. /// </summary> /// <param name="second">The second StringMetrics instance. This object will not be changed.</param> /// <exception cref="System.ArgumentException">Thrown when one instance has flipped axes and the other does not.</exception> 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 STRVector(left, top); Size = new STRVector(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); }
/// <summary> /// Draws a region of a texture on the screen. /// </summary> /// <param name="texture">The shader resource view of the texture to draw</param> /// <param name="position">Position of the center of the texture in the chosen coordinate system</param> /// <param name="size">Size of the texture in the chosen coordinate system. The size is specified in the screen's coordinate system.</param> /// <param name="center">Specify the texture's center in the chosen coordinate system. The center is specified in the texture's local coordinate system. E.g. for <paramref name="coordinateType"/>=CoordinateType.SNorm, the texture's center is defined by (0, 0).</param> /// <param name="rotationAngle">The angle in radians to rotate the texture. Positive values mean counter-clockwise rotation. Rotations can only be applied for relative or absolute coordinates. Consider using the Degrees or Radians helper structs.</param> /// <param name="coordinateType">A custom coordinate system in which to draw the texture</param> /// <param name="color">The color with which to multiply the texture</param> /// <param name="texCoords">Texture coordinates for the top left corner</param> /// <param name="texCoordsSize">Size of the region in texture coordinates</param> protected internal void Draw(object texture, STRVector position, STRVector size, STRVector center, double rotationAngle, STRVector texCoords, STRVector texCoordsSize, STRColor color, CoordinateType coordinateType) { if (texture == null) { return; } size.X = Math.Abs(size.X); size.Y = Math.Abs(size.Y); //Difference vectors from the center to the texture edges (in screen coordinates). STRVector left, up, right, down; if (coordinateType == CoordinateType.UNorm) { left = new STRVector(0 - center.X * size.X, 0); up = new STRVector(0, 0 - center.Y * size.Y); right = new STRVector((1 - center.X) * size.X, 0); down = new STRVector(0, (1 - center.Y) * size.Y); } else if (coordinateType == CoordinateType.SNorm) { left = new STRVector((-1 - center.X) * size.X / 2, 0); up = new STRVector(0, (1 - center.Y) * size.Y / 2); right = new STRVector((1 - center.X) * size.X / 2, 0); down = new STRVector(0, (-1 - center.Y) * size.Y / 2); } else { left = new STRVector(-center.X, 0); up = new STRVector(0, -center.Y); right = new STRVector(size.X - center.X, 0); down = new STRVector(0, size.Y - center.Y); } if (rotationAngle != 0) { if (coordinateType != CoordinateType.Absolute && coordinateType != CoordinateType.Relative) { //Normalized coordinates tend to be skewed when applying rotation throw new ArgumentException("Rotation is only allowed for relative or absolute coordinates", "rotationAngle"); } float sine = (float)Math.Sin(rotationAngle); float cosine = (float)Math.Cos(rotationAngle); left = Rotate(left, sine, cosine); right = Rotate(right, sine, cosine); up = Rotate(up, sine, cosine); down = Rotate(down, sine, cosine); } var data = new SpriteVertexLayout.Struct(); data.TexCoord = texCoords; data.TexCoordSize = texCoordsSize; data.Color = color.ToArgb(); data.TopLeft = ConvertCoordinate(position + up + left, coordinateType); data.TopRight = ConvertCoordinate(position + up + right, coordinateType); data.BottomLeft = ConvertCoordinate(position + down + left, coordinateType); data.BottomRight = ConvertCoordinate(position + down + right, coordinateType); if (AllowReorder) { //Is there already a sprite for this texture? if (textureSprites.ContainsKey(texture)) { //Add the sprite to the last segment for this texture var Segment = textureSprites[texture].Last(); AddIn(Segment, data); } else { //Add a new segment for this texture AddNew(texture, data); } } else { //Add a new segment for this texture AddNew(texture, data); } }
private STRVector Rotate(STRVector v, float sine, float cosine) { return(new STRVector(cosine * v.X + sine * v.Y, -sine * v.X + cosine * v.Y)); }
/// <summary> /// Draws a complete texture on the screen. /// </summary> /// <param name="texture">The shader resource view of the texture to draw</param> /// <param name="position">Position of the top left corner of the texture in the chosen coordinate system</param> /// <param name="size">Size of the texture in the chosen coordinate system. The size is specified in the screen's coordinate system.</param> /// <param name="center">Specify the texture's center in the chosen coordinate system. The center is specified in the texture's local coordinate system. E.g. for <paramref name="coordinateType"/>=CoordinateType.SNorm, the texture's center is defined by (0, 0).</param> /// <param name="rotationAngle">The angle in radians to rotate the texture. Positive values mean counter-clockwise rotation. Rotations can only be applied for relative or absolute coordinates. Consider using the Degrees or Radians helper structs.</param> /// <param name="coordinateType">A custom coordinate system in which to draw the texture</param> /// <param name="color">The color with which to multiply the texture</param> protected internal void Draw(object texture, STRVector position, STRVector size, STRVector center, double rotationAngle, STRColor color, CoordinateType coordinateType) { Draw(texture, position, size, center, rotationAngle, STRVector.Zero, new STRVector(1, 1), color, coordinateType); }
/// <summary> /// Draws a complete texture on the screen. /// </summary> /// <param name="texture">The shader resource view of the texture to draw</param> /// <param name="position">Position of the top left corner of the texture in the chosen coordinate system</param> /// <param name="size">Size of the texture in the chosen coordinate system. The size is specified in the screen's coordinate system.</param> /// <param name="coordinateType">A custom coordinate system in which to draw the texture</param> protected internal void Draw(object texture, STRVector position, STRVector size, CoordinateType coordinateType) { Draw(texture, position, size, STRVector.Zero, 0, coordinateType); }