Example #1
0
        private FontGlyph GetGlyph(Font font, int codepoint, int isize, int iblur, bool isBitmapRequired)
        {
            var       g       = 0;
            var       advance = 0;
            var       lsb     = 0;
            var       x0      = 0;
            var       y0      = 0;
            var       x1      = 0;
            var       y1      = 0;
            var       gw      = 0;
            var       gh      = 0;
            var       gx      = 0;
            var       gy      = 0;
            float     scale   = 0;
            FontGlyph glyph   = null;
            var       size    = isize / 10.0f;

            if (isize < 2)
            {
                return(null);
            }
            if (iblur > 20)
            {
                iblur = 20;
            }

            if (font.TryGetGlyph(codepoint, isize, iblur, out glyph))
            {
                if (!isBitmapRequired || glyph.X0 >= 0 && glyph.Y0 >= 0)
                {
                    return(glyph);
                }
            }
            g = font._font.fons__tt_getGlyphIndex(codepoint);
            if (g == 0)
            {
                throw new Exception(string.Format("Could not find glyph for codepoint {0}", codepoint));
            }

            scale = font._font.fons__tt_getPixelHeightScale(size);
            font._font.fons__tt_buildGlyphBitmap(g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1);

            var pad = FontGlyph.PadFromBlur(iblur);

            gw = x1 - x0 + pad * 2;
            gh = y1 - y0 + pad * 2;

            var currentAtlas = CurrentAtlas;

            if (isBitmapRequired)
            {
                if (!currentAtlas.AddRect(gw, gh, ref gx, ref gy))
                {
                    var ev = CurrentAtlasFull;
                    if (ev != null)
                    {
                        ev(this, EventArgs.Empty);
                    }

                    // This code will force creation of new atlas
                    _currentAtlas = null;
                    currentAtlas  = CurrentAtlas;

                    // Try to add again
                    if (!currentAtlas.AddRect(gw, gh, ref gx, ref gy))
                    {
                        throw new Exception(string.Format("Could not add rect to the newly created atlas. gw={0}, gh={1}", gw, gh));
                    }
                }
            }
            else
            {
                gx = -1;
                gy = -1;
            }

            if (glyph == null)
            {
                glyph = new FontGlyph
                {
                    Codepoint = codepoint,
                    Size      = isize,
                    Blur      = iblur
                };

                font.SetGlyph(codepoint, isize, iblur, glyph);
            }

            glyph.Index      = g;
            glyph.AtlasIndex = currentAtlas.Index;
            glyph.X0         = gx;
            glyph.Y0         = gy;
            glyph.X1         = glyph.X0 + gw;
            glyph.Y1         = glyph.Y0 + gh;
            glyph.XAdvance   = (int)(scale * advance * 10.0f);
            glyph.XOffset    = x0 - pad;
            glyph.YOffset    = y0 - pad;
            if (!isBitmapRequired)
            {
                return(glyph);
            }

            currentAtlas.RenderGlyph(font, glyph, gw, gh, scale);

            return(glyph);
        }
Example #2
0
        private FontGlyph GetGlyph(Font font, int codepoint, int isize, int iblur, bool isBitmapRequired, bool searchRecursively = true)
        {
            var       i          = 0;
            var       g          = 0;
            var       advance    = 0;
            var       lsb        = 0;
            var       x0         = 0;
            var       y0         = 0;
            var       x1         = 0;
            var       y1         = 0;
            var       gw         = 0;
            var       gh         = 0;
            var       gx         = 0;
            var       gy         = 0;
            var       x          = 0;
            var       y          = 0;
            float     scale      = 0;
            FontGlyph glyph      = null;
            int       h          = 0;
            var       size       = isize / 10.0f;
            var       pad        = 0;
            var       renderFont = font;

            if (isize < 2)
            {
                return(null);
            }
            if (iblur > 20)
            {
                iblur = 20;
            }
            pad = iblur + 2;

            if (font.TryGetGlyph(codepoint, isize, iblur, out glyph))
            {
                if (!isBitmapRequired || glyph.X0 >= 0 && glyph.Y0 >= 0)
                {
                    return(glyph);
                }
            }

            g = font._font.fons__tt_getGlyphIndex(codepoint);

            // Look for the glyph in other loaded fonts
            if (g == 0)
            {
                if (searchRecursively)
                {
                    foreach (var f in _fonts)
                    {
                        if (f == font)
                        {
                            continue;
                        }

                        var newGlyph = GetGlyph(f, codepoint, isize, iblur, true, false);
                        g = f._font.fons__tt_getGlyphIndex(codepoint);

                        if (g == 0)
                        {
                            continue;
                        }

                        return(newGlyph);
                    }

                    // No glyph was found at this point
                }
            }

            scale = renderFont._font.fons__tt_getPixelHeightScale(size);
            renderFont._font.fons__tt_buildGlyphBitmap(g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1);
            gw = x1 - x0 + pad * 2;
            gh = y1 - y0 + pad * 2;
            if (isBitmapRequired)
            {
                if (!_atlas.AddRect(gw, gh, ref gx, ref gy))
                {
                    var a = AtlasFull;
                    if (a != null)
                    {
                        a();
                    }

                    // Try again
                    if (!_atlas.AddRect(gw, gh, ref gx, ref gy))
                    {
                        throw new Exception("FONS_ATLAS_FULL");
                    }
                }
            }
            else
            {
                gx = -1;
                gy = -1;
            }

            if (glyph == null)
            {
                glyph = new FontGlyph
                {
                    Codepoint = codepoint,
                    Size      = isize,
                    Blur      = iblur
                };

                font.SetGlyph(codepoint, isize, iblur, glyph);
            }

            glyph.Index    = g;
            glyph.X0       = gx;
            glyph.Y0       = gy;
            glyph.X1       = glyph.X0 + gw;
            glyph.Y1       = glyph.Y0 + gh;
            glyph.XAdvance = (int)(scale * advance * 10.0f);
            glyph.XOffset  = x0 - pad;
            glyph.YOffset  = y0 - pad;
            if (!isBitmapRequired)
                return(glyph);

            fixed(byte *dst = &_texData[glyph.X0 + pad + (glyph.Y0 + pad) * _params_.Width])
            {
                renderFont._font.fons__tt_renderGlyphBitmap(dst, gw - pad * 2, gh - pad * 2, _params_.Width, scale,
                                                            scale, g);
            }

            fixed(byte *dst = &_texData[glyph.X0 + glyph.Y0 *_params_.Width])
            {
                for (y = 0; y < gh; y++)
                {
                    dst[y * _params_.Width]          = 0;
                    dst[gw - 1 + y * _params_.Width] = 0;
                }

                for (x = 0; x < gw; x++)
                {
                    dst[x] = 0;
                    dst[x + (gh - 1) * _params_.Width] = 0;
                }
            }

            if (iblur > 0)
            {
                fixed(byte *bdst = &_texData[glyph.X0 + glyph.Y0 *_params_.Width])
                {
                    Blur(bdst, gw, gh, _params_.Width, iblur);
                }
            }

            _dirtyRect[0] = Math.Min(_dirtyRect[0], glyph.X0);
            _dirtyRect[1] = Math.Min(_dirtyRect[1], glyph.Y0);
            _dirtyRect[2] = Math.Max(_dirtyRect[2], glyph.X1);
            _dirtyRect[3] = Math.Max(_dirtyRect[3], glyph.Y1);
            return(glyph);
        }