예제 #1
0
        public FontManager(Nvg nvg)
        {
            _nvg = nvg;

            for (uint i = 0; i < MAX_FONTIMAGES; i++)
            {
                _fontImages[i] = 0;
            }

            FonsParams fontParams = new()
            {
                width        = (int)INIT_FONTIMAGE_SIZE,
                height       = (int)INIT_FONTIMAGE_SIZE,
                flags        = (byte)FonsFlags.ZeroTopleft,
                renderCreate = null,
                renderUpdate = null,
                renderDraw   = null,
                renderDelete = null
            };

            Fontstash = new Fontstash(fontParams);

            _fontImages[0] = _nvg.renderer.CreateTexture(Texture.Alpha, new Vector2D <uint>((uint)fontParams.width, (uint)fontParams.height), 0, null);
            if (_fontImages[0] == 0)
            {
                _nvg.Dispose();
                throw new Exception("Failed to create dummy font atlas!");
            }
            _fontImageIdx = 0;
        }
예제 #2
0
        public Ui(Game game)
        {
            _game = game;
            _fons = _game.Fons;

            _widthInput          = new TextInput(1000.0f, 5.0f, 200.0f, 25.0f, 24, 2, "Width", "stdfont", _fons, () => _game.World.Reset(int.Parse(_widthInput.Text), _game.World.Height));
            _heightInput         = new TextInput(1000.0f, 40.0f, 200.0f, 25.0f, 24, 2, "Height", "stdfont", _fons, () => _game.World.Reset(_game.World.Width, int.Parse(_heightInput.Text)));
            _outputName          = new TextInput(1000.0f, 550.0f, 240.0f, 25.0f, 24, -1, "Name", "stdfont", _fons, () => _outputFont = _outputName.Text);
            _maxTurbinesInput    = new TextInput(1000.0f, 75.0f, 240.0f, 25.0f, 24, -1, "Turbines", "stdfont", _fons, () => _maxTurbines = int.Parse(_maxTurbinesInput.Text));
            _fiveStarEnergyInput = new TextInput(1000.0f, 600.0f, 200.0f, 25.0f, 24, -1, "Max E", "stdfont", _fons, () => _fiveStarEnergy = int.Parse(_fiveStarEnergyInput.Text));

            _grass    = new Button("Grass", 1000.0f, 200.0f, 50.0f, 30.0f, () => _currentSelected = TileType.Plains);
            _water    = new Button("Water", 1000.0f, 230.0f, 50.0f, 30.0f, () => _currentSelected = TileType.Water);
            _building = new Button("Building", 1000.0f, 260.0f, 50.0f, 30.0f, () => _currentSelected = TileType.Building);
            _forest   = new Button("Forest", 1000.0f, 290.0f, 50.0f, 30.0f, () => _currentSelected = TileType.Forest);
            _house    = new Button("House", 1000.0f, 320.0f, 50.0f, 30.0f, () => _currentSelected = TileType.House);
            _mountain = new Button("Mountain", 1000.0f, 350.0f, 50.0f, 30.0f, () => _currentSelected = TileType.Mountain);

            _zero  = new Button("Zero", 1150.0f, 200.0f, 50.0f, 30.0f, () => _currentWindPower = 0);
            _one   = new Button("One", 1150.0f, 230.0f, 50.0f, 30.0f, () => _currentWindPower = 1);
            _two   = new Button("Two", 1150.0f, 260.0f, 50.0f, 30.0f, () => _currentWindPower = 2);
            _three = new Button("Three", 1150.0f, 290.0f, 50.0f, 30.0f, () => _currentWindPower = 3);
            _four  = new Button("Four", 1150.0f, 320.0f, 50.0f, 30.0f, () => _currentWindPower = 4);
            _five  = new Button("Five", 1150.0f, 350.0f, 50.0f, 30.0f, () => _currentWindPower = 5);
            _six   = new Button("Six", 1150.0f, 380.0f, 50.0f, 30.0f, () => _currentWindPower = 6);
            _seven = new Button("Seven", 1150.0f, 410.0f, 50.0f, 30.0f, () => _currentWindPower = 7);
            _eight = new Button("Eight", 1150.0f, 440.0f, 50.0f, 30.0f, () => _currentWindPower = 8);
            _nine  = new Button("Nine", 1150.0f, 470.0f, 50.0f, 30.0f, () => _currentWindPower = 9);

            _exportButton = new Button("Export", 1000.0f, 500.0f, 240.0f, 25.0f, () => _game.World.Export(this));

            _tilePowerSelector = new ToggleButton("Tiles", "Wind", 1000.0f, 450.0f, 50.0f, 30.0f);
        }
예제 #3
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);
        }
예제 #4
0
        /// <summary>
        /// Finds a loaded font from specified name.
        /// </summary>
        /// <returns>Handle to it, or -1 if the font is not found.</returns>
        public static int FindFont(this Nvg nvg, string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return(-1);
            }

            Fontstash fons = nvg.fontManager.Fontstash;

            return(fons.GetFontByName(name));
        }
예제 #5
0
        /// <summary>
        /// Adds a fallback font by handle.
        /// </summary>
        public static bool AddFallbackFontId(this Nvg nvg, int baseFont, int fallbackFont)
        {
            if (baseFont == -1 || fallbackFont == -1)
            {
                return(false);
            }

            Fontstash fons = nvg.fontManager.Fontstash;

            return(fons.AddFallbackFont(baseFont, fallbackFont));
        }
예제 #6
0
        private void Init()
        {
            _gl = GL.GetApi(new GlfwContext(_glfw, _window));
            Assets.Init(_gl);
            Input.Init(_glfw, _window);

            _glFons = new GLFons(_gl);
            _fons   = _glFons.Create(512, 512, (int)FonsFlags.ZeroTopleft);
            _fons.AddFont("stdfont", "./fonts/DroidSerif-Regular.ttf");

            _world = new World.World(this);
            _ui    = new Ui(this);
        }
예제 #7
0
        public void Render(Fontstash fons)
        {
            if (_active)
            {
                fons.SetColour(0xFF00FFFF);
            }
            else
            {
                fons.SetColour(0xFF000000);
            }

            fons.SetFont(fons.GetFontByName("stdfont"));
            fons.SetSize(18.0f);
            fons.DrawText(_x + 2.0f, _y + _height, _active ? _activeText : _text);
        }
예제 #8
0
        /// <summary>
        /// Calculates the glyph x positions of the specified text. Only the sub-string will be used.<br/>
        /// Measures values are returned in local coordinate space.
        /// </summary>
        public static int TextGlyphPositions(this Nvg nvg, Vector2D <float> pos, string @string, string end, out GlyphPosition[] positions, int maxRows)
        {
            positions = new GlyphPosition[maxRows];

            Fontstash fons     = nvg.fontManager.Fontstash;
            State     state    = nvg.stateStack.CurrentState;
            float     scale    = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio;
            float     invscale = 1.0f / scale;
            FonsQuad  q        = new();
            int       npos     = 0;

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

            if (@string == end)
            {
                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);

            fons.TextIterInit(out FonsTextIter iter, pos.X * scale, pos.Y * scale, @string, end, FonsGlyphBitmap.Optional);
            FonsTextIter prevIter = iter;

            while (fons.TextIterNext(ref iter, ref q))
            {
                if (iter.prevGlyphIndex < 0 && nvg.fontManager.AllocTextAtlas())
                {
                    iter = prevIter;
                    fons.TextIterNext(ref iter, ref q);
                }
                prevIter          = iter;
                positions[npos++] = new GlyphPosition(iter.str, iter.x * invscale, MathF.Min(iter.x, q.x0) * invscale, MathF.Max(iter.nextx, q.x1) * invscale);
                if (npos >= maxRows)
                {
                    return(npos);
                }
            }

            return(npos);
        }
예제 #9
0
        public TextInput(float x, float y, float width, float height, int fontSize, int maxLength, string name, string font, Fontstash fons, Action onChange)
        {
            _x         = x;
            _y         = y;
            _width     = width;
            _height    = height;
            _fontSize  = fontSize;
            _maxLength = maxLength;
            _font      = font;
            _fons      = fons;
            _name      = name;
            _onChange  = onChange;

            Input.OnLeftDown += Click;
            Input.OnChar     += Write;
            Input.OnKeyDown  += Key;
        }
예제 #10
0
        private void Init()
        {
            var context = new GlfwContext(_glfw, _window);

            _gl       = GL.GetApi(context);
            _legacyGl = Silk.NET.OpenGL.Legacy.GL.GetApi(context);

            ResourceManager.Init(_gl);
            Input.Init(_glfw, _window);

            _glFons = new GLFons(_legacyGl);
            _fons   = _glFons.Create(512, 512, (int)FonsFlags.ZeroTopleft);
            _fons.AddFont("stdfont", "./Assets/Fonts/DroidSerif-Regular.ttf");

            _camera = new Camera(0.0f, 0.0f, 0.0f, 0.0f);

            _stateManager.AddState("Main Menu", new MenuState());
            _stateManager.AddState("Level Selector", new LevelSelectorState());
            _stateManager.AddState("Game", new GameState());

            MusicMaster.Start();
        }
예제 #11
0
        public void Render(LevelSelectorStateRenderer renderer, Fontstash fons)
        {
            renderer.RenderQuad(_button.X, _button.Y, _button.Width, _button.Height, new Vector4(_colour, Hovering ? 1.0f : 0.75f));

            float size = 32;
            float x    = _button.X + size / 1.5f;
            float y    = _button.Y + size * 1.5f;

            for (int i = 0; i < _data.bestRating; i++)
            {
                renderer.RenderTexturedQuad(_state.Star, x + i * size, y, size, -size);
            }

            renderer.PrepareLegacy();
            fons.SetColour(0xFFFFFFFF);
            fons.SetFont(fons.GetFontByName("stdfont"));
            fons.SetSize(24.0f);
            fons.SetAlign((int)FonsAlign.Center | (int)FonsAlign.Middle);
            fons.DrawText(_button.X + _button.Width / 2.0f, _button.Y + _button.Height / 2.0f, _data.name);
            fons.SetSize(16.0f);
            fons.DrawText(_button.X + _button.Width / 2.0f, _button.Y + _button.Height / 2.0f + 35.0f, "Last Time: " + _data.bestTime.ToString());
            renderer.EndLegacy();
        }
예제 #12
0
        /// <summary>
        /// Returns the vertical metrics based on the current text style.<br/>
        /// Measured values are returned in local coordinate space.
        /// </summary>
        public static void TextMetrics(this Nvg nvg, out float ascender, out float descender, out float lineh)
        {
            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)
            {
                ascender = descender = lineh = -1.0f;
                return;
            }

            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.VertMetrics(out ascender, out descender, out lineh);
            ascender  *= invscale;
            descender *= invscale;
            lineh     *= invscale;
        }
예제 #13
0
        /// <summary>
        /// Draws text string at specified location. Only the sub-string up to the end is drawn.
        /// </summary>
        public static float Text(this Nvg nvg, Vector2D <float> pos, string @string, string end)
        {
            Fontstash fons  = nvg.fontManager.Fontstash;
            State     state = nvg.stateStack.CurrentState;

            FonsQuad q = new();

            float scale     = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio;
            float invscale  = 1.0f / scale;
            bool  isFlipped = Maths.IsTransformFlipped(state.Transform);

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

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

            List <Vertex> vertices = new();

            fons.TextIterInit(out FonsTextIter iter, pos.X * scale, pos.Y * scale, @string, end, FonsGlyphBitmap.Requiered);
            FonsTextIter prevIter = iter;

            while (fons.TextIterNext(ref iter, ref q))
            {
                Vector2D <float>[] c = new Vector2D <float> [4];

                if (iter.prevGlyphIndex == -1)
                {
                    if (vertices.Count != 0)
                    {
                        nvg.fontManager.RenderText(vertices);
                        vertices.Clear();
                    }
                    if (!nvg.fontManager.AllocTextAtlas()) // no memory
                    {
                        break;
                    }
                    iter = prevIter;
                    _    = fons.TextIterNext(ref iter, ref q);
                    if (iter.prevGlyphIndex == -1)
                    {
                        break;
                    }
                }
                prevIter = iter;
                if (isFlipped)
                {
                    float tmp = q.y0;
                    q.y0 = q.y1;
                    q.y1 = tmp;

                    tmp  = q.t0;
                    q.t0 = q.t1;
                    q.t1 = tmp;
                }

                c[0] = nvg.TransformPoint(state.Transform, q.x0 * invscale, q.y0 * invscale);
                c[1] = nvg.TransformPoint(state.Transform, q.x1 * invscale, q.y0 * invscale);
                c[2] = nvg.TransformPoint(state.Transform, q.x1 * invscale, q.y1 * invscale);
                c[3] = nvg.TransformPoint(state.Transform, q.x0 * invscale, q.y1 * invscale);

                vertices.Add(new Vertex(c[0], q.s0, q.t0));
                vertices.Add(new Vertex(c[2], q.s1, q.t1));
                vertices.Add(new Vertex(c[1], q.s1, q.t0));
                vertices.Add(new Vertex(c[0], q.s0, q.t0));
                vertices.Add(new Vertex(c[3], q.s0, q.t1));
                vertices.Add(new Vertex(c[2], q.s1, q.t1));
            }

            nvg.fontManager.FlushTextTexture();
            nvg.fontManager.RenderText(vertices);

            return(iter.nextx / scale);
        }
예제 #14
0
        /// <summary>
        /// Resets fallback fonts by handle.
        /// </summary>
        public static void ResetFallbackFontsId(this Nvg nvg, int baseFont)
        {
            Fontstash fons = nvg.fontManager.Fontstash;

            fons.ResetFallbackFont(baseFont);
        }
예제 #15
0
        /// <param name="fontIndex">Specifies which font face to load from a .ttf/.ttc file</param>
        public static int CreateFontMemAtIndex(this Nvg nvg, string name, byte[] data, int freeData, int fontIndex)
        {
            Fontstash fons = nvg.fontManager.Fontstash;

            return(fons.AddFontMem(name, data, freeData, fontIndex));
        }
예제 #16
0
        /// <summary>
        /// Breaks the specified text into lines. Only the sub-string will be used.<br/>
        /// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.<br/>
        /// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
        /// </summary>
        public static int TextBreakLines(this Nvg nvg, string @string, string end, float breakRowWidth, out TextRow[] rows, int maxRows)
        {
            rows = new TextRow[maxRows];

            Fontstash fons = nvg.fontManager.Fontstash;

            State         state = nvg.stateStack.CurrentState;
            float         scale = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio;
            float         invscale = 1.0f / scale;
            FonsQuad      q = new();
            int           nrows = 0;
            float         rowStartX = 0.0f;
            float         rowWidth = 0.0f;
            float         rowMinX = 0.0f;
            float         rowMaxX = 0.0f;
            string        rowStart = null;
            string        rowEnd = null;
            string        wordStart = null;
            float         wordStartX = 0.0f;
            float         wordMinX = 0.0f;
            string        breakEnd = null;
            float         breakWidth = 0.0f;
            float         breakMaxX = 0.0f;
            CodepointType type, pType = CodepointType.Space;
            uint          pCodepoint = 0;

            if (maxRows == 0)
            {
                return(0);
            }

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

            if (@string == end || @string.Length == 0)
            {
                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);

            breakRowWidth *= scale;

            fons.TextIterInit(out FonsTextIter iter, 0, 0, @string, end, FonsGlyphBitmap.Optional);
            FonsTextIter prevIter = iter;

            while (fons.TextIterNext(ref iter, ref q))
            {
                if (iter.prevGlyphIndex < 0 && nvg.fontManager.AllocTextAtlas())
                {
                    iter = prevIter;
                    fons.TextIterNext(ref iter, ref q);
                }
                prevIter = iter;
                switch (iter.codepoint)
                {
                case 9:      // \t
                case 11:     // \v
                case 12:     // \f
                case 32:     // \space
                case 0x00a0: // NBSP
                    type = CodepointType.Space;
                    break;

                case 10:     // \n
                    type = pCodepoint == 13 ? CodepointType.Space : CodepointType.Newline;
                    break;

                case 13:     // \r
                    type = pCodepoint == 10 ? CodepointType.Space : CodepointType.Newline;
                    break;

                case 0x0085:     // NEL
                    type = CodepointType.Newline;
                    break;

                default:
                    if ((iter.codepoint >= 0x4E00 && iter.codepoint <= 0x9FFF) ||
                        (iter.codepoint >= 0x3000 && iter.codepoint <= 0x30FF) ||
                        (iter.codepoint >= 0xFF00 && iter.codepoint <= 0xFFEF) ||
                        (iter.codepoint >= 0x1100 && iter.codepoint <= 0x11FF) ||
                        (iter.codepoint >= 0x3130 && iter.codepoint <= 0x318F) ||
                        (iter.codepoint >= 0xAC00 && iter.codepoint <= 0xD7AF))
                    {
                        type = CodepointType.CJKChar;
                    }
                    else
                    {
                        type = CodepointType.Char;
                    }
                    break;
                }

                if (type == CodepointType.Newline)
                {
                    rows[nrows++] = new TextRow()
                    {
                        Start = rowStart ?? iter.str,
                        End   = rowEnd ?? iter.str,
                        Width = rowWidth * invscale,
                        MinX  = rowMinX * invscale,
                        MaxX  = rowMaxX * invscale,
                        Next  = iter.next
                    };

                    if (nrows >= maxRows)
                    {
                        return(nrows);
                    }

                    breakEnd   = rowStart;
                    breakWidth = 0.0f;
                    breakMaxX  = 0.0f;

                    rowStart = null;
                    rowEnd   = null;
                    rowWidth = 0.0f;
                    rowMinX  = rowMaxX = 0.0f;
                }
                else
                {
                    if (rowStart == null)
                    {
                        if (type == CodepointType.Char || type == CodepointType.CJKChar)
                        {
                            rowStartX  = iter.x;
                            rowStart   = iter.str;
                            rowEnd     = iter.next;
                            rowWidth   = iter.nextx - rowStartX;
                            rowMinX    = q.x0 - rowStartX;
                            rowMaxX    = q.x1 - rowStartX;
                            wordStart  = iter.str;
                            wordStartX = iter.x;
                            wordMinX   = q.x0 - rowStartX;

                            breakEnd   = rowStart;
                            breakWidth = 0.0f;
                            breakMaxX  = 0.0f;
                        }
                    }
                    else
                    {
                        float nextWidth = iter.nextx - rowStartX;

                        if (type == CodepointType.Char || type == CodepointType.CJKChar)
                        {
                            rowEnd   = iter.next;
                            rowWidth = iter.nextx - rowStartX;
                            rowMaxX  = q.x1 - rowStartX;
                        }

                        if (((pType == CodepointType.Char || pType == CodepointType.CJKChar) && type == CodepointType.Space) || type == CodepointType.CJKChar)
                        {
                            breakEnd   = iter.str;
                            breakWidth = rowWidth;
                            breakMaxX  = rowMaxX;
                        }

                        if ((pType == CodepointType.Space && (type == CodepointType.Char || type == CodepointType.CJKChar)) || type == CodepointType.CJKChar)
                        {
                            wordStart  = iter.str;
                            wordStartX = iter.x;
                            wordMinX   = q.x0;
                        }

                        if ((type == CodepointType.Char || type == CodepointType.CJKChar) && nextWidth > breakRowWidth)
                        {
                            if (breakEnd == rowStart)
                            {
                                rows[nrows++] = new TextRow()
                                {
                                    Start = rowStart,
                                    End   = iter.str,
                                    Width = rowWidth * invscale,
                                    MinX  = rowMinX * invscale,
                                    MaxX  = rowMaxX * invscale,
                                    Next  = iter.str
                                };

                                if (nrows >= maxRows)
                                {
                                    return(nrows);
                                }

                                rowStartX  = iter.x;
                                rowStart   = iter.str;
                                rowEnd     = iter.next;
                                rowWidth   = iter.nextx - rowStartX;
                                rowMinX    = q.x0 - rowStartX;
                                rowMaxX    = q.x1 - rowStartX;
                                wordStart  = iter.str;
                                wordStartX = iter.x;
                                wordMinX   = q.x0 - rowStartX;
                            }
                            else
                            {
                                rows[nrows++] = new TextRow()
                                {
                                    Start = rowStart,
                                    End   = breakEnd,
                                    Width = breakWidth * invscale,
                                    MinX  = rowMinX * invscale,
                                    MaxX  = breakMaxX * invscale,
                                    Next  = wordStart
                                };

                                if (nrows >= maxRows)
                                {
                                    return(nrows);
                                }

                                rowStartX = wordStartX;
                                rowStart  = wordStart;
                                rowEnd    = iter.next;
                                rowWidth  = iter.nextx - rowStartX;
                                rowMinX   = wordMinX - rowStartX;
                                rowMaxX   = q.x1 - rowStartX;
                            }

                            breakEnd   = rowStart;
                            breakWidth = 0.0f;
                            breakMaxX  = 0.0f;
                        }
                    }
                }

                pCodepoint = iter.codepoint;
                pType      = type;
            }

            if (rowStart != null)
            {
                rows[nrows++] = new TextRow()
                {
                    Start = rowStart,
                    End   = rowEnd,
                    Width = rowWidth * invscale,
                    MinX  = rowMinX * invscale,
                    MaxX  = rowMaxX * invscale,
                    Next  = end
                };
            }

            return(nrows);
        }
예제 #17
0
        /// <param name="fontIndex">Specifies which font face to load from a .ttf/.ttc file</param>
        public static int CreateFontAtIndex(this Nvg nvg, string name, string fileName, int fontIndex)
        {
            Fontstash fons = nvg.fontManager.Fontstash;

            return(fons.AddFont(name, fileName, fontIndex));
        }
예제 #18
0
        /// <summary>
        /// Sets the font face based on specified name of current text style.
        /// </summary>
        public static void FontFace(this Nvg nvg, string font)
        {
            Fontstash fons = nvg.fontManager.Fontstash;

            nvg.stateStack.CurrentState.FontId = fons.GetFontByName(font);
        }
예제 #19
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));
        }