private void Dispose(bool disposing) { if (this.disposedValue == false) { if (disposing) { // Dispose managed resources. } // Dispose unmanaged resources. FullDictionary <char, GlyphInfo> dict = this.GlyphInfoDictionary; this.GlyphInfoDictionary = null; if (dict != null) { dict.Clear(); } Font font = this.GlyphFont; this.GlyphFont = null; if (font != null) { font.Dispose(); } Texture texture = this.TextureObj; this.TextureObj = null; if (texture != null) { texture.Dispose(); } } this.disposedValue = true; }
private static Bitmap PaintTexture(int textureWidth, int textureHeight, FullDictionary <char, GlyphInfo> fullDictionary, Font font) { var bitmap = new Bitmap(textureWidth, textureHeight); using (var graphics = Graphics.FromImage(bitmap)) { graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; foreach (var item in fullDictionary) { Size oneSize = graphics.MeasureString(string.Format("{0}", item.Key), font).ToSize(); using (var oneBitmap = new Bitmap(oneSize.Width, oneSize.Height)) { using (var oneGrphics = Graphics.FromImage(oneBitmap)) { oneGrphics.DrawString(string.Format("{0}", item.Key), font, Brushes.Red, 0, 0); } graphics.DrawImage(oneBitmap, item.Value.ToRectangle(), new Rectangle((oneSize.Width - item.Value.width) / 2, 0, item.Value.width, item.Value.height), GraphicsUnit.Pixel); } } } return(bitmap); }
unsafe private void SetupGlyphTexCoord(string content, IFontTexture fontTexture) { FullDictionary <char, GlyphInfo> charInfoDict = fontTexture.GlyphInfoDictionary; IntPtr pointer = this.uvBuffer.MapBuffer(MapBufferAccess.WriteOnly); var array = (TextModel.GlyphTexCoord *)pointer.ToPointer(); int width = fontTexture.TextureSize.Width; int height = fontTexture.TextureSize.Height; /* * 0 3 4 6 8 11 12 15 * ------- ------- ------- ------- * | | | | | | | | * | | | | | | | | * | | | | | | | | * ------- ------- ------- ------- * 1 2 5 6 9 10 13 14 */ for (int i = 0; i < content.Length; i++) { char ch = content[i]; GlyphInfo info = fontTexture.GlyphInfoDictionary[ch]; const int shrimp = 0; array[i] = new TextModel.GlyphTexCoord( //new vec2(0, 0), //new vec2(0, 1), //new vec2(1, 1), //new vec2(1, 0) new vec2((float)(info.xoffset + shrimp) / (float)width, (float)(info.yoffset) / (float)height), new vec2((float)(info.xoffset + shrimp) / (float)width, (float)(info.yoffset + info.height) / (float)height), new vec2((float)(info.xoffset - shrimp + info.width) / (float)width, (float)(info.yoffset + info.height) / (float)height), new vec2((float)(info.xoffset - shrimp + info.width) / (float)width, (float)(info.yoffset) / (float)height) ); } this.uvBuffer.UnmapBuffer(); }
private static FullDictionary <char, GlyphInfo> GetGlyphDict(Font font, string charSet) { var dict = new FullDictionary <char, GlyphInfo>(GlyphInfo.Default); using (var bmp = new Bitmap(1, 1)) { using (var graphics = Graphics.FromImage(bmp)) { foreach (var c in charSet) { Size oneSize = graphics.MeasureString(string.Format("{0}", c), font).ToSize(); Size doubleSize = graphics.MeasureString(string.Format("{0}{0}", c), font).ToSize(); // TODO: Log this. if (oneSize.Height != doubleSize.Height) { continue; } if (oneSize.Width >= doubleSize.Width) { continue; } Size charSize = new Size(doubleSize.Width - oneSize.Width, oneSize.Height); var info = new GlyphInfo(0, 0, charSize.Width, charSize.Height); dict.Add(c, info); } } } return(dict); }
unsafe private void SetupGlyphPositions(string content, FontResource fontResource) { FullDictionary <char, CharacterInfo> charInfoDict = fontResource.CharInfoDict; OpenGL.BindBuffer(BufferTarget.ArrayBuffer, this.model.positionBufferPtr.BufferId); IntPtr pointer = OpenGL.MapBuffer(BufferTarget.ArrayBuffer, MapBufferAccess.ReadWrite); var array = (GlyphPosition *)pointer.ToPointer(); int currentWidth = 0; int currentHeight = 0; /* * 0 3 4 7 8 11 12 15 * ------- ------- ------- ------- * | | | | | | | | * | | | | | | | | * | | | | | | | | * ------- ------- ------- ------- * 1 2 5 6 9 10 13 14 */ for (int i = 0; i < content.Length; i++) { char ch = content[i]; CharacterInfo info = charInfoDict[ch]; array[i] = new GlyphPosition( new vec2(currentWidth, currentHeight + fontResource.FontHeight), new vec2(currentWidth, currentHeight), new vec2(currentWidth + info.width, currentHeight), new vec2(currentWidth + info.width, currentHeight + fontResource.FontHeight)); currentWidth += info.width + fontResource.FontHeight / 10; } // move to center for (int i = 0; i < content.Length; i++) { GlyphPosition position = array[i]; position.leftUp.x -= currentWidth / 2.0f; //position.leftUp.x /= currentWidth / factor; position.leftDown.x -= currentWidth / 2.0f; //position.leftDown.x /= currentWidth / factor; position.rightUp.x -= currentWidth / 2.0f; //position.rightUp.x /= currentWidth / factor; position.rightDown.x -= currentWidth / 2.0f; //position.rightDown.x /= currentWidth / factor; position.leftUp.y -= (currentHeight + fontResource.FontHeight) / 2.0f; position.leftDown.y -= (currentHeight + fontResource.FontHeight) / 2.0f; position.rightUp.y -= (currentHeight + fontResource.FontHeight) / 2.0f; position.rightDown.y -= (currentHeight + fontResource.FontHeight) / 2.0f; position.leftUp.x /= (currentHeight + fontResource.FontHeight); position.leftDown.x /= (currentHeight + fontResource.FontHeight); position.rightUp.x /= (currentHeight + fontResource.FontHeight); position.rightDown.x /= (currentHeight + fontResource.FontHeight); position.leftUp.y /= (currentHeight + fontResource.FontHeight); position.leftDown.y /= (currentHeight + fontResource.FontHeight); position.rightUp.y /= (currentHeight + fontResource.FontHeight); position.rightDown.y /= (currentHeight + fontResource.FontHeight); array[i] = position; } OpenGL.UnmapBuffer(BufferTarget.ArrayBuffer); OpenGL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
public static XElement ToXElement(this FullDictionary <char, CharacterInfo> dict) { XElement result = new XElement(strCharacterInfoDict, from item in dict select KeyValuePairHelper.ToXElement(item)); return(result); }
unsafe private void SetupGlyphPositions(string content, IFontTexture fontTexture) { FullDictionary <char, GlyphInfo> charInfoDict = fontTexture.GlyphInfoDictionary; IntPtr pointer = this.positionBuffer.MapBuffer(MapBufferAccess.ReadWrite); var array = (TextModel.GlyphPosition *)pointer.ToPointer(); float currentWidth = 0; int currentHeight = 0; /* * 0 3 4 7 8 11 12 15 * ------- ------- ------- ------- * | | | | | | | | * | | | | | | | | * | | | | | | | | * ------- ------- ------- ------- * 1 2 5 6 9 10 13 14 */ for (int i = 0; i < content.Length; i++) { char ch = content[i]; GlyphInfo info = charInfoDict[ch]; array[i] = new TextModel.GlyphPosition( new vec2(currentWidth, currentHeight + fontTexture.GlyphHeight), new vec2(currentWidth, currentHeight), new vec2(currentWidth + info.width, currentHeight), new vec2(currentWidth + info.width, currentHeight + fontTexture.GlyphHeight)); currentWidth += info.width + fontTexture.GlyphHeight / 10; } // move to center for (int i = 0; i < content.Length; i++) { TextModel.GlyphPosition position = array[i]; position.leftUp.x -= currentWidth / 2.0f; //position.leftUp.x /= currentWidth / factor; position.leftDown.x -= currentWidth / 2.0f; //position.leftDown.x /= currentWidth / factor; position.rightUp.x -= currentWidth / 2.0f; //position.rightUp.x /= currentWidth / factor; position.rightDown.x -= currentWidth / 2.0f; //position.rightDown.x /= currentWidth / factor; position.leftUp.y -= (currentHeight + fontTexture.GlyphHeight) / 2.0f; position.leftDown.y -= (currentHeight + fontTexture.GlyphHeight) / 2.0f; position.rightUp.y -= (currentHeight + fontTexture.GlyphHeight) / 2.0f; position.rightDown.y -= (currentHeight + fontTexture.GlyphHeight) / 2.0f; position.leftUp.x /= (currentHeight + fontTexture.GlyphHeight); position.leftDown.x /= (currentHeight + fontTexture.GlyphHeight); position.rightUp.x /= (currentHeight + fontTexture.GlyphHeight); position.rightDown.x /= (currentHeight + fontTexture.GlyphHeight); position.leftUp.y /= (currentHeight + fontTexture.GlyphHeight); position.leftDown.y /= (currentHeight + fontTexture.GlyphHeight); position.rightUp.y /= (currentHeight + fontTexture.GlyphHeight); position.rightDown.y /= (currentHeight + fontTexture.GlyphHeight); array[i] = position; } this.positionBuffer.UnmapBuffer(); }
private static void BlitCharacter(int pixelSize, int maxWidth, FullDictionary <char, CharacterInfo> dict, ref int currentX, ref int currentY, Graphics g, FontFace typeface, char c) { if (c == ' ') { int width = pixelSize / 3; if (currentX + xInterval + width >= maxWidth) { currentX = 0; currentY += yInterval + pixelSize; if (currentY + yInterval + pixelSize >= maxWidth) { throw new Exception("Texture Size not big enough for reuqired characters."); } } Bitmap glyphBitmap = new Bitmap(width + xInterval, pixelSize + yInterval); //float yoffset = pixelSize * 3 / 4 - glyph.HorizontalMetrics.Bearing.Y; g.DrawImage(glyphBitmap, currentX + xInterval, currentY + yInterval); CharacterInfo info = new CharacterInfo(currentX, currentY, width + xInterval, pixelSize + yInterval); dict.Add(c, info); glyphBitmap.Dispose(); currentX += width; } else { Surface surface; Glyph glyph; if (RenderGlyph(typeface, c, pixelSize, out surface, out glyph)) { if (currentX + xInterval + surface.Width >= maxWidth) { currentX = 0; currentY += yInterval + pixelSize; if (currentY + yInterval + pixelSize >= maxWidth) { throw new Exception("Texture Size not big enough for reuqired characters."); } } Bitmap glyphBitmap = GetGlyphBitmap(surface); const int a = 5; const int b = 8; //float yoffset = pixelSize * a / b - glyph.HorizontalMetrics.Bearing.Y; #if DEBUG g.DrawRectangle(redPen, currentX + xInterval, currentY + yInterval + pixelSize * a / b - glyph.HorizontalMetrics.Bearing.Y, glyphBitmap.Width, glyphBitmap.Height); g.DrawRectangle(greenPen, currentX, currentY, glyphBitmap.Width + xInterval, yInterval + pixelSize - 1); #endif g.DrawImage(glyphBitmap, currentX + xInterval, currentY + yInterval + pixelSize * a / b - glyph.HorizontalMetrics.Bearing.Y, glyphBitmap.Width, glyphBitmap.Height); CharacterInfo info = new CharacterInfo(currentX, currentY, glyphBitmap.Width + xInterval, yInterval + pixelSize - 1); dict.Add(c, info); glyphBitmap.Dispose(); currentX += xInterval + surface.Width; } surface.Dispose(); } }
private static int GetTextureWidth(FullDictionary <char, GlyphInfo> fullDictionary) { int totalAera = 0; foreach (var item in fullDictionary) { int area = item.Value.width * item.Value.height; totalAera += area; } return((int)Math.Sqrt(totalAera)); }
public static FullDictionary <char, CharacterInfo> Parse(XElement xElement) { FullDictionary <char, CharacterInfo> result = new FullDictionary <char, CharacterInfo>( CharacterInfo.Default); foreach (var item in xElement.Elements(KeyValuePairHelper.strKeyValuePair)) { KeyValuePair <char, CharacterInfo> pair = KeyValuePairHelper.Parse(item); result.Add(pair.Key, pair.Value); } return(result); }
private static int GetGlyphHeight(FullDictionary <char, GlyphInfo> fullDictionary, int textureWidth) { int glyphHeight = 0; foreach (var item in fullDictionary) { int height = item.Value.height; if (glyphHeight < height) { glyphHeight = height; } } return(glyphHeight); }
unsafe private void SetupGlyphPositions(string content, IFontTexture fontTexture) { FullDictionary <char, GlyphInfo> charInfoDict = fontTexture.GlyphInfoDictionary; IntPtr pointer = this.positionBuffer.MapBuffer(MapBufferAccess.ReadWrite); var array = (TextModel.GlyphPosition *)pointer.ToPointer(); float currentWidth = 0; int currentHeight = 0; /* * 0 3 4 7 8 11 12 15 * ------- ------- ------- ------- * | | | | | | | | * | | | | | | | | * | | | | | | | | * ------- ------- ------- ------- * 1 2 5 6 9 10 13 14 */ for (int i = 0; i < content.Length; i++) { char ch = content[i]; GlyphInfo info = charInfoDict[ch]; array[i] = new TextModel.GlyphPosition( new vec2(currentWidth, currentHeight + fontTexture.GlyphHeight), new vec2(currentWidth, currentHeight), new vec2(currentWidth + info.width, currentHeight), new vec2(currentWidth + info.width, currentHeight + fontTexture.GlyphHeight)); currentWidth += info.width + fontTexture.GlyphHeight / 10; } switch (this.Alignment) { case TextAlignment.Center: Move2Center(content, array, currentWidth, currentHeight, fontTexture); break; case TextAlignment.Left: Move2Left(content, array, currentWidth, currentHeight, fontTexture); break; case TextAlignment.Right: Move2Right(content, array, currentWidth, currentHeight, fontTexture); break; default: break; } this.positionBuffer.UnmapBuffer(); }
/// <summary> /// /// </summary> /// <param name="stream">".ttf", or ".otf"</param> /// <param name="pixelSize">The desired size of the font, in pixels.</param> /// <returns></returns> private static FontResource Load(Stream stream, char firstChar, char lastChar, int pixelSize = 32) { InitStandardWidths(); int count = lastChar - firstChar + 1; int maxWidth = GetMaxWidth(pixelSize, count); var fontResource = new FontResource(); fontResource.FontHeight = pixelSize + yInterval; var dict = new FullDictionary <char, CharacterInfo>(CharacterInfo.Default); fontResource.CharInfoDict = dict; var bitmap = new Bitmap(maxWidth, maxWidth, PixelFormat.Format24bppRgb); int currentX = 0, currentY = 0; Graphics g = Graphics.FromImage(bitmap); /* * this.FontHeight = int.Parse(config.Attribute(strFontHeight).Value); * this.CharInfoDict = CharacterInfoDictHelper.Parse( * config.Element(CharacterInfoDictHelper.strCharacterInfoDict)); */ //using (var file = File.OpenRead(ttfFilename)) { var typeface = new FontFace(stream); for (char c = firstChar; c <= lastChar; c++) { BlitCharacter(pixelSize, maxWidth, dict, ref currentX, ref currentY, g, typeface, c); if (c == char.MaxValue) { break; } } } g.Dispose(); Bitmap finalBitmap = ShortenBitmap(bitmap, maxWidth, currentY + yInterval + pixelSize + (pixelSize / 10 > 1 ? pixelSize / 10 : 1)); bitmap.Dispose(); fontResource.InitTexture(finalBitmap); finalBitmap.Dispose(); return(fontResource); }
private static int LayoutGlyphs(FullDictionary <char, GlyphInfo> fullDictionary, int textureWidth, int glyphHeight) { int cursorX = 0, cursorY = 0; foreach (var item in fullDictionary) { int width = item.Value.width; int height = item.Value.height; if (cursorX + width > textureWidth) { cursorX = 0; cursorY += glyphHeight; } item.Value.xoffset = cursorX; item.Value.yoffset = cursorY; cursorX += width; } return(cursorY + glyphHeight); }
private static FontResource LoadFromSomeChars(Stream stream, int pixelSize, IEnumerable <char> targets) { FontResource fontResource; int count = targets.Count(); int maxWidth = GetMaxWidth(pixelSize, count); fontResource = new FontResource(); fontResource.FontHeight = pixelSize + yInterval; var dict = new FullDictionary <char, CharacterInfo>(CharacterInfo.Default); fontResource.CharInfoDict = dict; var bitmap = new Bitmap(maxWidth, maxWidth, PixelFormat.Format24bppRgb); int currentX = 0, currentY = 0; Graphics g = Graphics.FromImage(bitmap); /* * this.FontHeight = int.Parse(config.Attribute(strFontHeight).Value); * this.CharInfoDict = CharacterInfoDictHelper.Parse( * config.Element(CharacterInfoDictHelper.strCharacterInfoDict)); */ { var typeface = new FontFace(stream); foreach (char c in targets) { BlitCharacter(pixelSize, maxWidth, dict, ref currentX, ref currentY, g, typeface, c); } } g.Dispose(); Bitmap finalBitmap = ShortenBitmap(bitmap, maxWidth, currentY + yInterval + pixelSize + (pixelSize / 10 > 1 ? pixelSize / 10 : 1)); bitmap.Dispose(); fontResource.InitTexture(finalBitmap); finalBitmap.Dispose(); return(fontResource); }
unsafe private void SetupGlyphTexCoord(string content, FontResource fontResource) { FullDictionary <char, CharacterInfo> charInfoDict = fontResource.CharInfoDict; OpenGL.BindBuffer(BufferTarget.ArrayBuffer, this.model.uvBufferPtr.BufferId); IntPtr pointer = OpenGL.MapBuffer(BufferTarget.ArrayBuffer, MapBufferAccess.WriteOnly); var array = (GlyphTexCoord *)pointer.ToPointer(); int width = fontResource.TextureSize.Width; int height = fontResource.TextureSize.Height; /* * 0 3 4 6 8 11 12 15 * ------- ------- ------- ------- * | | | | | | | | * | | | | | | | | * | | | | | | | | * ------- ------- ------- ------- * 1 2 5 6 9 10 13 14 */ for (int i = 0; i < content.Length; i++) { char ch = content[i]; CharacterInfo info = fontResource.CharInfoDict[ch]; const int shrimp = 0; array[i] = new GlyphTexCoord( //new vec2(0, 0), //new vec2(0, 1), //new vec2(1, 1), //new vec2(1, 0) new vec2((float)(info.xoffset + shrimp) / (float)width, (float)(info.yoffset) / (float)height), new vec2((float)(info.xoffset + shrimp) / (float)width, (float)(info.yoffset + info.height) / (float)height), new vec2((float)(info.xoffset - shrimp + info.width) / (float)width, (float)(info.yoffset + info.height) / (float)height), new vec2((float)(info.xoffset - shrimp + info.width) / (float)width, (float)(info.yoffset) / (float)height) ); } OpenGL.UnmapBuffer(BufferTarget.ArrayBuffer); OpenGL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
internal FontBitmap() { this.GlyphInfoDictionary = new FullDictionary <char, GlyphInfo>(GlyphInfo.Default); }