예제 #1
0
        /// <summary>
        /// Measures the specified text string. Parameter bounds contains the bounds of the text.<br/>
        /// Measured values are returned in local coordinate space.
        /// </summary>
        /// <param name="bounds">Contains the bounds of the text when returned.</param>
        /// <returns>The horizontal advance of the measured text (i.e. where the next character should be drawn).</returns>
        public static float TextBounds(this Nvg nvg, Vector2D <float> pos, string @string, string end, out Rectangle <float> bounds)
        {
            bounds = default;

            Fontstash fons     = nvg.fontManager.Fontstash;
            State     state    = nvg.stateStack.CurrentState;
            float     scale    = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio;
            float     invscale = 1.0f / scale;

            if (state.FontId == Fontstash.INVALID)
            {
                return(0);
            }

            fons.SetSize(state.FontSize * scale);
            fons.SetSpacing(state.LetterSpacing * scale);
            fons.SetBlur(state.FontBlur * scale);
            fons.SetAlign((int)state.TextAlign);
            fons.SetFont(state.FontId);

            float width = fons.TextBounds(pos.X * scale, pos.Y * scale, @string, end, out float[] bs);

            if (bs != null)
            {
                fons.LineBounds(pos.Y * scale, out bs[1], out bs[3]);
                bounds = new Rectangle <float>()
                {
                    Origin = new Vector2D <float>(bs[0] * invscale, bs[1] * invscale),
                    Size   = new Vector2D <float>((bs[2] - bs[0]) * invscale, (bs[3] - bs[1]) * invscale)
                };
            }

            return(width * invscale);
        }
예제 #2
0
        /// <summary>
        /// Measures the specified multi-text string.<br/>
        /// Measured values are returned in local space.
        /// </summary>
        /// <param name="bounds">Contains the bounds box of the multi-text when returned.</param>
        public static void TextBoxBounds(this Nvg nvg, Vector2D <float> pos, float breakRowWidth, string @string, string end, out Rectangle <float> bounds)
        {
            Fontstash fons     = nvg.fontManager.Fontstash;
            State     state    = nvg.stateStack.CurrentState;
            float     scale    = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio;
            float     invscale = 1.0f / scale;
            int       nrows;
            Align     oldAlign = state.TextAlign;
            Align     hAlign   = state.TextAlign & (Align.Left | Align.Centre | Align.Right);
            Align     vAlign   = state.TextAlign & (Align.Top | Align.Middle | Align.Bottom | Align.Baseline);

            if (state.FontId == Fontstash.INVALID)
            {
                bounds = default;
                return;
            }

            nvg.TextMetrics(out _, out _, out float lineh);

            state.TextAlign = Align.Left | vAlign;

            float minX = pos.X, maxX = pos.X;
            float minY = pos.Y, maxY = pos.Y;

            fons.SetSize(state.FontSize * scale);
            fons.SetSpacing(state.LetterSpacing * scale);
            fons.SetBlur(state.FontBlur * scale);
            fons.SetAlign((int)state.TextAlign);
            fons.SetFont(state.FontId);
            fons.LineBounds(0, out float rMinY, out float rMaxY);
            rMinY *= invscale;
            rMaxY *= invscale;

            while ((nrows = TextBreakLines(nvg, @string, end, breakRowWidth, out TextRow[] rows, 2)) != 0)
            {
                for (uint i = 0; i < nrows; i++)
                {
                    float rMinX, rMaxX;
                    float dx = 0.0f;
                    if (hAlign.HasFlag(Align.Left))
                    {
                        dx = 0.0f;
                    }
                    else if (hAlign.HasFlag(Align.Centre))
                    {
                        dx = breakRowWidth * 0.5f - rows[i].Width * 0.5f;
                    }
                    else if (hAlign.HasFlag(Align.Right))
                    {
                        dx = breakRowWidth - rows[i].Width;
                    }
                    rMinX = pos.X + rows[i].MinX + dx;
                    rMaxX = pos.X + rows[i].MaxX + dx;
                    minX  = MathF.Min(minX, rMinX);
                    maxX  = MathF.Max(maxX, rMaxX);

                    minY = MathF.Min(minY, pos.Y + rMinY);
                    maxY = MathF.Max(maxY, pos.Y + rMaxY);

                    pos.Y += lineh * state.LineHeight;
                }
                @string = rows[nrows - 1].Next;
            }

            state.TextAlign = oldAlign;

            bounds = new Rectangle <float>(new Vector2D <float>(minX, minY), new Vector2D <float>(maxX, maxY) - new Vector2D <float>(minX, minY));
        }