public FontSystem(IFontLoader fontLoader, ITexture2DCreator textureCreator, int width, int height, int blurAmount = 0, int strokeAmount = 0, bool premultiplyAlpha = true) { if (fontLoader == null) { throw new ArgumentNullException(nameof(fontLoader)); } if (textureCreator == null) { throw new ArgumentNullException(nameof(textureCreator)); } _fontLoader = fontLoader; _textureCreator = textureCreator; if (width <= 0) { throw new ArgumentOutOfRangeException(nameof(width)); } if (height <= 0) { throw new ArgumentOutOfRangeException(nameof(height)); } if (blurAmount < 0 || blurAmount > 20) { throw new ArgumentOutOfRangeException(nameof(blurAmount)); } if (strokeAmount < 0 || strokeAmount > 20) { throw new ArgumentOutOfRangeException(nameof(strokeAmount)); } if (strokeAmount != 0 && blurAmount != 0) { throw new ArgumentException("Cannot have both blur and stroke."); } BlurAmount = blurAmount; StrokeAmount = strokeAmount; PremultiplyAlpha = premultiplyAlpha; _size = new Point(width, height); }
public FontSystem(ITexture2DCreator textureCreator, int width, int height, int blurAmount = 0, int strokeAmount = 0, bool premultiplyAlpha = true) : this(StbTrueTypeSharpFontLoader.Instance, textureCreator, width, height, blurAmount, strokeAmount, premultiplyAlpha) { }
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); }