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); }