private FontGlyph GetGlyphWithoutBitmap(Dictionary <int, FontGlyph> glyphs, int codepoint) { FontGlyph glyph = null; if (glyphs.TryGetValue(codepoint, out glyph)) { return(glyph); } Font font; var g = GetCodepointIndex(codepoint, out font); if (g == 0) { return(null); } int advance = 0, lsb = 0, x0 = 0, y0 = 0, x1 = 0, y1 = 0; font.BuildGlyphBitmap(g, FontSize, font.Scale, ref advance, ref lsb, ref x0, ref y0, ref x1, ref y1); var pad = FontGlyph.PadFromBlur(Blur); var gw = x1 - x0 + pad * 2; var gh = y1 - y0 + pad * 2; glyph = new FontGlyph { Font = font, Codepoint = codepoint, Size = FontSize, Blur = Blur, Index = g, Bounds = new Rectangle(0, 0, gw, gh), XAdvance = (int)(font.Scale * advance * 10.0f), XOffset = x0 - pad, YOffset = y0 - pad }; glyphs[codepoint] = glyph; return(glyph); }
private FontGlyph GetGlyphWithoutBitmap(int codepoint) { FontGlyph glyph = null; if (_glyphs.TryGetValue(codepoint, out glyph)) { return(glyph); } IFontSource font; var g = FontSystem.GetCodepointIndex(codepoint, out font); if (g == null) { return(null); } int advance = 0, x0 = 0, y0 = 0, x1 = 0, y1 = 0; font.GetGlyphMetrics(g.Value, FontSize, out advance, out x0, out y0, out x1, out y1); var pad = Math.Max(FontGlyph.PadFromBlur(FontSystem.BlurAmount), FontGlyph.PadFromBlur(FontSystem.StrokeAmount)); var gw = x1 - x0 + pad * 2; var gh = y1 - y0 + pad * 2; var offset = FontGlyph.PadFromBlur(FontSystem.BlurAmount); glyph = new FontGlyph { Codepoint = codepoint, Id = g.Value, Size = FontSize, Font = font, Bounds = new Rectangle(0, 0, gw, gh), XAdvance = advance, XOffset = x0 - offset, YOffset = y0 - offset }; _glyphs[codepoint] = glyph; return(glyph); }
FontGlyph GetGlyphWithoutBitmap(GlyphCollection collection, int codepoint) { FontGlyph glyph = null; if (collection.Glyphs.TryGetValue(codepoint, out glyph)) { return(glyph); } Font font; var g = GetCodepointIndex(codepoint, out font); if (g == 0) { return(null); } int advance = 0, lsb = 0, x0 = 0, y0 = 0, x1 = 0, y1 = 0; font.BuildGlyphBitmap(g, font.Scale, ref advance, ref lsb, ref x0, ref y0, ref x1, ref y1); var pad = Math.Max(FontGlyph.PadFromBlur(BlurAmount), FontGlyph.PadFromBlur(StrokeAmount)); var gw = x1 - x0 + pad * 2; var gh = y1 - y0 + pad * 2; var offset = FontGlyph.PadFromBlur(BlurAmount); glyph = new FontGlyph { Font = font, Codepoint = codepoint, Size = FontSize, Index = g, Bounds = new Rectangle(0, 0, gw, gh), XAdvance = (int)(font.Scale * advance * 10.0f), XOffset = x0 - offset, YOffset = y0 - offset }; collection.Glyphs[codepoint] = glyph; return(glyph); }
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); }
public void RenderGlyph(GraphicsDevice device, FontGlyph glyph, int blurAmount, int strokeAmount) { var pad = Math.Max(FontGlyph.PadFromBlur(blurAmount), FontGlyph.PadFromBlur(strokeAmount)); // Render glyph to byte buffer var bufferSize = glyph.Bounds.Width * glyph.Bounds.Height; var buffer = _byteBuffer; if ((buffer == null) || (buffer.Length < bufferSize)) { buffer = new byte[bufferSize]; _byteBuffer = buffer; } Array.Clear(buffer, 0, bufferSize); var g = glyph.Index; var colorSize = glyph.Bounds.Width * glyph.Bounds.Height; var colorBuffer = _colorBuffer; if ((colorBuffer == null) || (colorBuffer.Length < colorSize)) { colorBuffer = new Color[colorSize]; _colorBuffer = colorBuffer; } fixed(byte *dst = &buffer[pad + pad *glyph.Bounds.Width]) { glyph.Font.RenderGlyphBitmap(dst, glyph.Bounds.Width - pad * 2, glyph.Bounds.Height - pad * 2, glyph.Bounds.Width, g); } if (strokeAmount > 0) { var width = glyph.Bounds.Width; var top = width * strokeAmount; var bottom = (glyph.Bounds.Height - strokeAmount) * glyph.Bounds.Width; var right = glyph.Bounds.Width - strokeAmount; var left = strokeAmount; byte d; for (var i = 0; i < colorSize; ++i) { var col = buffer[i]; var black = 0; if (col == 255) { colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = 255; continue; } if (i >= top) { black = buffer[i - top]; } if (i < bottom) { d = buffer[i + top]; black = ((255 - d) * black + 255 * d) / 255; } if (i % width >= left) { d = buffer[i - strokeAmount]; black = ((255 - d) * black + 255 * d) / 255; } if (i % width < right) { d = buffer[i + strokeAmount]; black = ((255 - d) * black + 255 * d) / 255; } if (black == 0) { if (col == 0) { colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = 0; //black transparency to suit stroke continue; } #if PREMULTIPLIEDALPHA colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = col; #else colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = 255; colorBuffer[i].A = col; #endif } else { if (col == 0) { colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = 0; colorBuffer[i].A = (byte)black; continue; } #if PREMULTIPLIEDALPHA var alpha = ((255 - col) * black + 255 * col) / 255; colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = (byte)((alpha * col) / 255); colorBuffer[i].A = (byte)alpha; #else colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = col; colorBuffer[i].A = (byte)(((255 - col) * black + 255 * col) / 255); #endif } } } else { if (blurAmount > 0) { fixed(byte *bdst = &buffer[0]) { Blur(bdst, glyph.Bounds.Width, glyph.Bounds.Height, glyph.Bounds.Width, blurAmount); } } for (var i = 0; i < colorSize; ++i) { var c = buffer[i]; #if PREMULTIPLIEDALPHA colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = colorBuffer[i].A = c; #else colorBuffer[i].R = colorBuffer[i].G = colorBuffer[i].B = 255; colorBuffer[i].A = c; #endif } } // Write to texture if (Texture == null) { Texture = new Texture2D(device, Width, Height); } #if TEXTURESETDATAEXT fixed(Color *p = colorBuffer) #if FNA Texture.SetDataPointerEXT(0, glyph.Bounds, (IntPtr)p, colorSize * sizeof(Color)); #else Texture.SetDataEXT(0, 0, glyph.Bounds, (IntPtr)p, colorSize * sizeof(Color)); #endif #else Texture.SetData(0, 0, glyph.Bounds, colorBuffer, 0, colorSize); #endif }
public void RenderGlyph(ITexture2DCreator textureCreator, FontGlyph glyph, int blurAmount, int strokeAmount, bool premultiplyAlpha) { var pad = Math.Max(FontGlyph.PadFromBlur(blurAmount), FontGlyph.PadFromBlur(strokeAmount)); // Render glyph to byte buffer var bufferSize = glyph.Bounds.Width * glyph.Bounds.Height; var buffer = _byteBuffer; if ((buffer == null) || (buffer.Length < bufferSize)) { buffer = new byte[bufferSize]; _byteBuffer = buffer; } Array.Clear(buffer, 0, bufferSize); var colorBuffer = _colorBuffer; if ((colorBuffer == null) || (colorBuffer.Length < bufferSize * 4)) { colorBuffer = new byte[bufferSize * 4]; _colorBuffer = colorBuffer; } glyph.Font.RasterizeGlyphBitmap(glyph.Id, glyph.Size, buffer, pad + pad * glyph.Bounds.Width, glyph.Bounds.Width - pad * 2, glyph.Bounds.Height - pad * 2, glyph.Bounds.Width); if (strokeAmount > 0) { var width = glyph.Bounds.Width; var top = width * strokeAmount; var bottom = (glyph.Bounds.Height - strokeAmount) * glyph.Bounds.Width; var right = glyph.Bounds.Width - strokeAmount; var left = strokeAmount; byte d; for (var i = 0; i < bufferSize; ++i) { var ci = i * 4; var col = buffer[i]; var black = 0; if (col == 255) { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = colorBuffer[ci + 3] = 255; continue; } if (i >= top) { black = buffer[i - top]; } if (i < bottom) { d = buffer[i + top]; black = ((255 - d) * black + 255 * d) / 255; } if (i % width >= left) { d = buffer[i - strokeAmount]; black = ((255 - d) * black + 255 * d) / 255; } if (i % width < right) { d = buffer[i + strokeAmount]; black = ((255 - d) * black + 255 * d) / 255; } if (black == 0) { if (col == 0) { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = colorBuffer[ci + 3] = 0; //black transparency to suit stroke continue; } if (premultiplyAlpha) { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = colorBuffer[ci + 3] = col; } else { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = 255; colorBuffer[ci + 3] = col; } } else { if (col == 0) { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = 0; colorBuffer[ci + 3] = (byte)black; continue; } if (premultiplyAlpha) { var alpha = ((255 - col) * black + 255 * col) / 255; colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = (byte)((alpha * col) / 255); colorBuffer[ci + 3] = (byte)alpha; } else { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = col; colorBuffer[ci + 3] = (byte)(((255 - col) * black + 255 * col) / 255); } } } } else { if (blurAmount > 0) { fixed(byte *bdst = &buffer[0]) { Blur(bdst, glyph.Bounds.Width, glyph.Bounds.Height, glyph.Bounds.Width, blurAmount); } } for (var i = 0; i < bufferSize; ++i) { var ci = i * 4; var c = buffer[i]; if (premultiplyAlpha) { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = colorBuffer[ci + 3] = c; } else { colorBuffer[ci] = colorBuffer[ci + 1] = colorBuffer[ci + 2] = 255; colorBuffer[ci + 3] = c; } } } // Write to texture if (Texture == null) { Texture = textureCreator.Create(Width, Height); } Texture.SetData(glyph.Bounds, colorBuffer); }