예제 #1
0
        private FontGlyph GetGlyph(Font font, int codepoint, int isize, int iblur, int bitmapOption)
        {
            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       added      = 0;
            var       renderFont = font;

            if (isize < 2)
            {
                return(null);
            }
            if (iblur > 20)
            {
                iblur = 20;
            }
            pad = iblur + 2;
            h   = HashInt(codepoint) & (256 - 1);
            i   = font.Lut[h];
            while (i != -1)
            {
                if (font.Glyphs[i].Codepoint == codepoint && font.Glyphs[i].Size == isize &&
                    font.Glyphs[i].Blur == iblur)
                {
                    glyph = font.Glyphs[i];
                    if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL || glyph.X0 >= 0 && glyph.Y0 >= 0)
                    {
                        return(glyph);
                    }
                    break;
                }

                i = font.Glyphs[i].Next;
            }

            g = font._font.fons__tt_getGlyphIndex((int)codepoint);
            if (g == 0)
            {
                for (i = 0; i < font.FallbacksCount; ++i)
                {
                    var fallbackFont  = _fonts[font.Fallbacks[i]];
                    var fallbackIndex = fallbackFont._font.fons__tt_getGlyphIndex((int)codepoint);
                    if (fallbackIndex != 0)
                    {
                        g          = fallbackIndex;
                        renderFont = fallbackFont;
                        break;
                    }
                }
            }

            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 (bitmapOption == FONS_GLYPH_BITMAP_REQUIRED)
            {
                added = _atlas.AddRect(gw, gh, &gx, &gy);
                if (added == 0)
                {
                    throw new Exception("FONS_ATLAS_FULL");
                }
            }
            else
            {
                gx = -1;
                gy = -1;
            }

            if (glyph == null)
            {
                glyph           = AllocGlyph(font);
                glyph.Codepoint = codepoint;
                glyph.Size      = isize;
                glyph.Blur      = iblur;
                glyph.Next      = 0;
                glyph.Next      = font.Lut[h];
                font.Lut[h]     = font.GlyphsNumber - 1;
            }

            glyph.Index    = g;
            glyph.X0       = (int)gx;
            glyph.Y0       = (int)gy;
            glyph.X1       = (int)(glyph.X0 + gw);
            glyph.Y1       = (int)(glyph.Y0 + gh);
            glyph.XAdvance = (int)(scale * advance * 10.0f);
            glyph.XOffset  = (int)(x0 - pad);
            glyph.YOffset  = (int)(y0 - pad);
            if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL)
                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);
        }