private static extern uint GetGlyphOutline(IntPtr hdc, uint ch, uint format, out GLYPHMETRICS gm, uint cb, IntPtr buffer, ref MAT2 mat2);
public static Image GetGlyphOutlineImage(Font font, char ch, out GLYPHMETRICS gm) { byte[] alpha; int size; using (FontDC dc = new FontDC(font)) { MAT2 mat = new MAT2(); mat.eM11.value = 1; mat.eM22.value = 1; size = (int)GetGlyphOutline(dc.handle, ch, (uint)GlyphOutline.GGO_GRAY8_BITMAP, out gm, 0, IntPtr.Zero, ref mat); if (size <= 0) { return null; } IntPtr bufptr = Marshal.AllocHGlobal(size); try { alpha = new byte[size]; GetGlyphOutline(dc.handle, ch, (uint)GlyphOutline.GGO_GRAY8_BITMAP, out gm, (uint)size, bufptr, ref mat); Marshal.Copy(bufptr, alpha, 0, size); } finally { Marshal.FreeHGlobal(bufptr); } } int stride = (int)(gm.gmBlackBoxX + 3) & ~3; // dword alinged Bitmap bmp = new Bitmap(stride, (int)gm.gmBlackBoxY, PixelFormat.Format32bppArgb); BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int bmpSize = bd.Stride * bd.Height; byte[] bmpValues = new byte[bmpSize]; Marshal.Copy(bd.Scan0, bmpValues, 0, bmpSize); const int bias = 0x40; for (int i = 0; i < size; i++) { byte v = (byte)((int)alpha[i] * 255 / bias); bmpValues[i * 4 + 0] = 0xff; bmpValues[i * 4 + 1] = 0xff; bmpValues[i * 4 + 2] = 0xff; bmpValues[i * 4 + 3] = v; } Marshal.Copy(bmpValues, 0, bd.Scan0, bmpSize); bmp.UnlockBits(bd); return bmp; }