// Rasterizes a single character glyph. private Glyph ImportGlyph(char character, Face face) { uint glyphIndex = face.GetCharIndex(character); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); // Render the character. BitmapContent glyphBitmap = null; if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) { glyphBitmap = new PixelBitmapContent<byte>(face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows); byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; //if the character bitmap has 1bpp we have to expand the buffer data to get the 8bpp pixel data //each byte in bitmap.bufferdata contains the value of to 8 pixels in the row //if bitmap is of width 10, each row has 2 bytes with 10 valid bits, and the last 6 bits of 2nd byte must be discarded if(face.Glyph.Bitmap.PixelMode == PixelMode.Mono) { //variables needed for the expansion, amount of written data, length of the data to write int written = 0, length = face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows; for(int i = 0; written < length; i++) { //width in pixels of each row int width = face.Glyph.Bitmap.Width; while(width > 0) { //valid data in the current byte int stride = MathHelper.Min(8, width); //copy the valid bytes to pixeldata //System.Array.Copy(ExpandByte(face.Glyph.Bitmap.BufferData[i]), 0, gpixelAlphas, written, stride); ExpandByteAndCopy(face.Glyph.Bitmap.BufferData[i], stride, gpixelAlphas, written); written += stride; width -= stride; if(width > 0) i++; } } } else Marshal.Copy(face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); glyphBitmap.SetPixelData(gpixelAlphas); } if (glyphBitmap == null) { var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; var gVA = face.Size.Metrics.Height >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; glyphBitmap = new PixelBitmapContent<byte>(gHA, gVA); } // not sure about this at all var abc = new ABCFloat (); abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; abc.B = face.Glyph.Metrics.Width >> 6; abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); // Construct the output Glyph object. return new Glyph(character, glyphBitmap) { XOffset = -(face.Glyph.Advance.X >> 6), XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), CharacterWidths = abc }; }
// Rasterizes a single character glyph. static Glyph ImportGlyph(char character, Face face, Brush brush, StringFormat stringFormat, Bitmap bitmap, System.Drawing.Graphics graphics) { string characterString = character.ToString(); uint glyphIndex = face.GetCharIndex(character); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); // Measure the size of this character. var width = (int)face.Glyph.Advance.X >> 6; var height = (int)face.Glyph.Metrics.Height >> 6; SizeF size = new SizeF(width, height); int characterWidth = (int)Math.Ceiling(size.Width); int characterHeight = (int)Math.Ceiling(size.Height); // Pad to make sure we capture any overhangs (negative ABC spacing, etc.) int padWidth = characterWidth; int padHeight = characterHeight / 2; int bitmapWidth = characterWidth + padWidth * 2; int bitmapHeight = characterHeight + padHeight * 2; if (bitmapWidth > MaxGlyphSize || bitmapHeight > MaxGlyphSize) { throw new Exception("Excessively large glyph won't fit in my lazily implemented fixed size temp surface."); } // Render the character. graphics.Clear(System.Drawing.Color.Black); if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) { BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; Marshal.Copy(face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); for (int j = 0; j < gpixelAlphas.Length; j++) { int pixelOffset = (j / data.Width) * data.Stride + (j % data.Width * 4); Marshal.WriteByte(data.Scan0, pixelOffset + 3, gpixelAlphas [j]); } bitmap.UnlockBits(data); } // Clone the newly rendered image. Bitmap glyphBitmap = null; if (face.Glyph.Bitmap.Width > 0 || face.Glyph.Bitmap.Rows > 0) { glyphBitmap = bitmap.Clone(new System.Drawing.Rectangle(0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), PixelFormat.Format32bppArgb); } else { var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; var gVA = face.Glyph.Metrics.VerticalAdvance >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; glyphBitmap = new Bitmap(gHA, gVA); } BitmapUtils.ConvertToGrey(glyphBitmap); // not sure about this at all var abc = new ABCFloat(); abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; abc.B = face.Glyph.Metrics.Width >> 6; abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); // Query its ABC spacing. //float? abc = GetCharacterWidth(character, font, graphics); // if (glyphBitmap == null) // Console.WriteLine("null"); // Construct the output Glyph object. return(new Glyph(character, glyphBitmap) { XOffset = -padWidth, XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), CharacterWidths = abc }); }
// Rasterizes a single character glyph. private Glyph ImportGlyph(char character, Face face) { uint glyphIndex = face.GetCharIndex(character); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); // Render the character. BitmapContent glyphBitmap = null; if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) { glyphBitmap = new PixelBitmapContent <byte>(face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows); byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; //if the character bitmap has 1bpp we have to expand the buffer data to get the 8bpp pixel data //each byte in bitmap.bufferdata contains the value of to 8 pixels in the row //if bitmap is of width 10, each row has 2 bytes with 10 valid bits, and the last 6 bits of 2nd byte must be discarded if (face.Glyph.Bitmap.PixelMode == PixelMode.Mono) { //variables needed for the expansion, amount of written data, length of the data to write int written = 0, length = face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows; for (int i = 0; written < length; i++) { //width in pixels of each row int width = face.Glyph.Bitmap.Width; while (width > 0) { //valid data in the current byte int stride = MathHelper.Min(8, width); //copy the valid bytes to pixeldata //System.Array.Copy(ExpandByte(face.Glyph.Bitmap.BufferData[i]), 0, gpixelAlphas, written, stride); ExpandByteAndCopy(face.Glyph.Bitmap.BufferData[i], stride, gpixelAlphas, written); written += stride; width -= stride; if (width > 0) { i++; } } } } else { Marshal.Copy(face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); } glyphBitmap.SetPixelData(gpixelAlphas); } if (glyphBitmap == null) { var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; var gVA = face.Size.Metrics.Height >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; glyphBitmap = new PixelBitmapContent <byte>(gHA, gVA); } // not sure about this at all var abc = new ABCFloat(); abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; abc.B = face.Glyph.Metrics.Width >> 6; abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); // Construct the output Glyph object. return(new Glyph(character, glyphBitmap) { XOffset = -(face.Glyph.Advance.X >> 6), XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), CharacterWidths = abc }); }
// Rasterizes a single character glyph. static Glyph ImportGlyph(char character, Face face, Brush brush, StringFormat stringFormat, Bitmap bitmap, System.Drawing.Graphics graphics) { uint glyphIndex = face.GetCharIndex(character); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); // Render the character. graphics.Clear(System.Drawing.Color.Black); if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) { BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; Marshal.Copy(face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); for (int j = 0; j < gpixelAlphas.Length; j++) { int pixelOffset = (j / data.Width) * data.Stride + (j % data.Width * 4); Marshal.WriteByte(data.Scan0, pixelOffset + 3, gpixelAlphas [j]); } bitmap.UnlockBits(data); } // Clone the newly rendered image. Bitmap glyphBitmap = null; if (face.Glyph.Bitmap.Width > 0 || face.Glyph.Bitmap.Rows > 0) { glyphBitmap = bitmap.Clone(new System.Drawing.Rectangle(0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), PixelFormat.Format32bppArgb); } else { var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; var gVA = face.Size.Metrics.Height >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; glyphBitmap = new Bitmap(gHA, gVA); } BitmapUtils.ConvertAlphaToGrey(glyphBitmap); // not sure about this at all var abc = new ABCFloat(); abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; abc.B = face.Glyph.Metrics.Width >> 6; abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); // Construct the output Glyph object. return(new Glyph(character, glyphBitmap) { XOffset = -(face.Glyph.Advance.X >> 6), XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), CharacterWidths = abc }); }
// Rasterizes a single character glyph. static Glyph ImportGlyph(char character, Face face, Brush brush, StringFormat stringFormat, Bitmap bitmap, System.Drawing.Graphics graphics) { string characterString = character.ToString(); uint glyphIndex = face.GetCharIndex(character); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); // Measure the size of this character. var width = (int)face.Glyph.Advance.X >> 6; var height = (int)face.Glyph.Metrics.Height >> 6; SizeF size = new SizeF(width, height); int characterWidth = (int)Math.Ceiling(size.Width); int characterHeight = (int)Math.Ceiling(size.Height); // Pad to make sure we capture any overhangs (negative ABC spacing, etc.) int padWidth = characterWidth; int padHeight = characterHeight / 2; int bitmapWidth = characterWidth + padWidth * 2; int bitmapHeight = characterHeight + padHeight * 2; if (bitmapWidth > MaxGlyphSize || bitmapHeight > MaxGlyphSize) throw new Exception("Excessively large glyph won't fit in my lazily implemented fixed size temp surface."); // Render the character. graphics.Clear(System.Drawing.Color.Black); if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) { BitmapData data = bitmap.LockBits (new System.Drawing.Rectangle (0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; Marshal.Copy (face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); for (int j = 0; j < gpixelAlphas.Length; j++) { int pixelOffset = (j / data.Width) * data.Stride + (j % data.Width * 4); Marshal.WriteByte (data.Scan0, pixelOffset + 3, gpixelAlphas [j]); } bitmap.UnlockBits (data); } // Clone the newly rendered image. Bitmap glyphBitmap = null; if (face.Glyph.Bitmap.Width > 0 || face.Glyph.Bitmap.Rows > 0) glyphBitmap = bitmap.Clone(new System.Drawing.Rectangle(0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), PixelFormat.Format32bppArgb); else { var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; var gVA = face.Glyph.Metrics.VerticalAdvance >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; glyphBitmap = new Bitmap (gHA, gVA); } BitmapUtils.ConvertToGrey(glyphBitmap); // not sure about this at all var abc = new ABCFloat (); abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; abc.B = face.Glyph.Metrics.Width >> 6; abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); // Query its ABC spacing. //float? abc = GetCharacterWidth(character, font, graphics); // if (glyphBitmap == null) // Console.WriteLine("null"); // Construct the output Glyph object. return new Glyph(character, glyphBitmap) { XOffset = -padWidth, XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), CharacterWidths = abc }; }
// Rasterizes a single character glyph. static Glyph ImportGlyph(char character, Face face, Brush brush, StringFormat stringFormat, Bitmap bitmap, System.Drawing.Graphics graphics) { uint glyphIndex = face.GetCharIndex(character); face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); // Render the character. graphics.Clear(System.Drawing.Color.Black); if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) { BitmapData data = bitmap.LockBits (new System.Drawing.Rectangle (0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; Marshal.Copy (face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); for (int j = 0; j < gpixelAlphas.Length; j++) { int pixelOffset = (j / data.Width) * data.Stride + (j % data.Width * 4); Marshal.WriteByte (data.Scan0, pixelOffset + 3, gpixelAlphas [j]); } bitmap.UnlockBits (data); } // Clone the newly rendered image. Bitmap glyphBitmap = null; if (face.Glyph.Bitmap.Width > 0 || face.Glyph.Bitmap.Rows > 0) glyphBitmap = bitmap.Clone(new System.Drawing.Rectangle(0, 0, face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows), PixelFormat.Format32bppArgb); else { var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; var gVA = face.Size.Metrics.Height >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; glyphBitmap = new Bitmap (gHA, gVA); } BitmapUtils.ConvertAlphaToGrey(glyphBitmap); // not sure about this at all var abc = new ABCFloat (); abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; abc.B = face.Glyph.Metrics.Width >> 6; abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); // Construct the output Glyph object. return new Glyph(character, glyphBitmap) { XOffset = -(face.Glyph.Advance.X >> 6), XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), CharacterWidths = abc }; }