internal void RenderGlyphOnAtlas(DynamicFontGlyph glyph) { var currentAtlas = CurrentAtlas; int gx = 0, gy = 0; var gw = glyph.Bounds.Width; var gh = glyph.Bounds.Height; if (!currentAtlas.AddRect(gw, gh, ref gx, ref gy)) { CurrentAtlasFull?.Invoke(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)); } } glyph.Bounds.X = gx; glyph.Bounds.Y = gy; #if MONOGAME || FNA || STRIDE currentAtlas.RenderGlyph(_graphicsDevice, glyph, BlurAmount, StrokeAmount, PremultiplyAlpha); #else currentAtlas.RenderGlyph(_textureCreator, glyph, BlurAmount, StrokeAmount, PremultiplyAlpha); #endif glyph.Texture = currentAtlas.Texture; }
private DynamicFontGlyph GetGlyphWithoutBitmap(int codepoint) { DynamicFontGlyph glyph; if (Glyphs.TryGetValue(codepoint, out glyph)) { return(glyph); } int fontSourceIndex; var g = FontSystem.GetCodepointIndex(codepoint, out fontSourceIndex); if (g == null) { Glyphs[codepoint] = null; return(null); } var fontSize = (int)(FontSize * FontSystem.FontResolutionFactor); var font = FontSystem.FontSources[fontSourceIndex]; int advance, x0, y0, x1, y1; font.GetGlyphMetrics(g.Value, fontSize, out advance, out x0, out y0, out x1, out y1); var pad = Math.Max(DynamicFontGlyph.PadFromBlur(FontSystem.BlurAmount), DynamicFontGlyph.PadFromBlur(FontSystem.StrokeAmount)); var gw = (x1 - x0) + pad * 2; var gh = (y1 - y0) + pad * 2; var offset = DynamicFontGlyph.PadFromBlur(FontSystem.BlurAmount); glyph = new DynamicFontGlyph { Codepoint = codepoint, Id = g.Value, Size = fontSize, FontSourceIndex = fontSourceIndex, Bounds = new Rectangle(0, 0, gw, gh), XAdvance = advance, XOffset = x0 - offset, YOffset = y0 - offset }; Glyphs[codepoint] = glyph; return(glyph); }
private DynamicFontGlyph GetGlyphWithoutBitmap(int codepoint) { DynamicFontGlyph 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(DynamicFontGlyph.PadFromBlur(FontSystem.BlurAmount), DynamicFontGlyph.PadFromBlur(FontSystem.StrokeAmount)); var gw = x1 - x0 + pad * 2; var gh = y1 - y0 + pad * 2; var offset = DynamicFontGlyph.PadFromBlur(FontSystem.BlurAmount); glyph = new DynamicFontGlyph { 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); }
internal void RenderGlyphOnAtlas(ITexture2DManager device, DynamicFontGlyph glyph) #endif { var textureSize = new Point(TextureWidth, TextureHeight); if (ExistingTexture != null) { #if MONOGAME || FNA || STRIDE textureSize = new Point(ExistingTexture.Width, ExistingTexture.Height); #else textureSize = device.GetTextureSize(ExistingTexture); #endif } int gx = 0, gy = 0; var gw = glyph.Bounds.Width; var gh = glyph.Bounds.Height; var currentAtlas = GetCurrentAtlas(device, textureSize.X, textureSize.Y); if (!currentAtlas.AddRect(gw, gh, ref gx, ref gy)) { CurrentAtlasFull?.Invoke(this, EventArgs.Empty); // This code will force creation of new atlas _currentAtlas = null; currentAtlas = GetCurrentAtlas(device, textureSize.X, textureSize.Y); // 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)); } } glyph.Bounds.X = gx; glyph.Bounds.Y = gy; currentAtlas.RenderGlyph(device, glyph, FontSources[glyph.FontSourceIndex], BlurAmount, StrokeAmount, PremultiplyAlpha, KernelWidth, KernelHeight); glyph.Texture = currentAtlas.Texture; }
internal void RenderGlyphOnAtlas(GraphicsDevice device, DynamicFontGlyph glyph)
public void RenderGlyph(ITexture2DManager textureManager, DynamicFontGlyph glyph, IFontSource fontSource, int blurAmount, int strokeAmount, bool premultiplyAlpha, int kernelWidth, int kernelHeight) #endif { var pad = Math.Max(DynamicFontGlyph.PadFromBlur(blurAmount), DynamicFontGlyph.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; } fontSource.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; } } } #if MONOGAME || FNA || STRIDE // Write to texture if (Texture == null) { Texture = Texture2DManager.CreateTexture(graphicsDevice, Width, Height); } Texture2DManager.SetTextureData(Texture, glyph.Bounds, colorBuffer); #else // Write to texture if (Texture == null) { Texture = textureManager.CreateTexture(Width, Height); } textureManager.SetTextureData(Texture, glyph.Bounds, colorBuffer); #endif }
public void RenderGlyph(GraphicsDevice graphicsDevice, DynamicFontGlyph glyph, IFontSource fontSource, int blurAmount, int strokeAmount, bool premultiplyAlpha, int kernelWidth, int kernelHeight)
public void RenderGlyph(GraphicsDevice graphicsDevice, DynamicFontGlyph glyph, int blurAmount, int strokeAmount, bool premultiplyAlpha)