Esempio n. 1
0
        private void IterateStringEm(string text, Vector2 position, bool draw, float realFontSize, Color4 color, CoordinateType coordinateType,
                                     out StringMetrics metrics)
        {
            var scale = realFontSize / FontSize;

            IterateString(text, position, draw, scale, color, coordinateType, out metrics);
        }
Esempio n. 2
0
        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;
                }
            }
        }
Esempio n. 3
0
        /// <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
            var xAxisFlipped = Size.X < 0;
            var yAxisFlipped = Size.Y < 0;

            // Check, if axes of both instances point in the same direction
            if (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 (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
            var top    = findTopMost(TopLeft.Y, second.TopLeft.Y);
            var bottom = findBottomMost(TopLeft.Y + Size.Y, second.TopLeft.Y + second.Size.Y);
            var left   = findLeftMost(TopLeft.X, second.TopLeft.X);
            var right  = findRightMost(TopLeft.X + Size.X, second.TopLeft.X + second.Size.X);

            // Find new overhangs
            var topOverhangPos    = findTopMost(FullRectTopLeft.Y, second.FullRectTopLeft.Y);
            var bottomOverhangPos = findBottomMost(FullRectTopLeft.Y + FullRectSize.Y, second.FullRectTopLeft.Y + second.FullRectSize.Y);
            var leftOverhangPos   = findLeftMost(FullRectTopLeft.X, second.FullRectTopLeft.X);
            var rightOverhangPos  = findRightMost(FullRectTopLeft.X + 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);
        }
Esempio n. 4
0
        /// <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);
        }
Esempio n. 5
0
        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;
            }
        }