Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

GetGlyphOutline (gdi32)
 
.
Summary

C# Signature:

[DllImport("gdi32.dll")]
static extern uint GetGlyphOutline(IntPtr hdc, uint uChar, uint uFormat,
   out GLYPHMETRICS lpgm, uint cbBuffer, IntPtr lpvBuffer, ref MAT2 lpmat2);

VB Signature

Public Declare Function GetGlyphOutline Lib "gdi32.dll"( _
   hdc As IntPtr, uChar As UInteger, uFormat As UInteger, _
   ByRef lpgm As GLYPHMETRICS, cbBuffer As UInteger, lpvBuffer As IntPtr, ByRef lpmat2 As MAT2) As Integer

User-Defined Types:

[StructLayout(LayoutKind.Sequential)]

public struct TTPOLYGONHEADER

{

    public int cb;
    public int dwType;
    [MarshalAs(UnmanagedType.Struct)] public POINTFX pfxStart;

}

[StructLayout(LayoutKind.Sequential)]

    public struct TTPOLYCURVEHEADER

{

    public short wType;
    public short cpfx;

}

[StructLayout(LayoutKind.Sequential)]

public struct FIXED

{

    public short fract;
    public short value;

}

[StructLayout(LayoutKind.Sequential)]

public struct MAT2

{

    [MarshalAs(UnmanagedType.Struct)] public FIXED eM11;
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM12;
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM21;
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM22;

}

[StructLayout(LayoutKind.Sequential)]

    public struct POINT

{

    public int x;
    public int y;

}

[StructLayout(LayoutKind.Sequential)]

    public struct POINTFX

{

    [MarshalAs(UnmanagedType.Struct)] public FIXED x;
    [MarshalAs(UnmanagedType.Struct)] public FIXED y;

}

[StructLayout(LayoutKind.Sequential)]

    public struct GLYPHMETRICS

{

    public int gmBlackBoxX;
    public int gmBlackBoxY;
    [MarshalAs(UnmanagedType.Struct)] public POINT gmptGlyphOrigin;
    [MarshalAs(UnmanagedType.Struct)] public POINTFX gmptGlyphOrigin;
    public short gmCellIncX;
    public short gmCellIncY;

}

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

        // Parse a glyph outline in native format
        public static void GetGlyphShape(Font font, Char c)
        {            
            GLYPHMETRICS metrics = new GLYPHMETRICS();            
            MAT2 matrix = new MAT2();
            matrix.eM11.value = 1;
            matrix.eM12.value = 0;
            matrix.eM21.value = 0;
            matrix.eM22.value = 1;

            using(Bitmap b = new Bitmap(1,1))
            {
                using(Graphics g = Graphics.FromImage(b))
                {
                    IntPtr hdc = g.GetHdc();                                        
                    IntPtr prev = SelectObject(hdc, font.ToHfont());                    
                    int bufferSize = (int)GetGlyphOutline(hdc, (uint)c, (uint)2, out metrics, 0, IntPtr.Zero, ref matrix);
                    IntPtr buffer = Marshal.AllocHGlobal(bufferSize);
                    try
                    {            
                        uint ret;
                        if((ret = GetGlyphOutline(hdc, (uint)c, (uint)2, out metrics, (uint)bufferSize, buffer, ref matrix)) > 0)
                        {                            
                            int polygonHeaderSize = Marshal.SizeOf(typeof(TTPOLYGONHEADER));
                            int curveHeaderSize = Marshal.SizeOf(typeof(TTPOLYCURVEHEADER));
                            int pointFxSize = Marshal.SizeOf(typeof(POINTFX));

                            int index = 0;
                            while(index < bufferSize)
                            {                                
                                TTPOLYGONHEADER header = (TTPOLYGONHEADER)Marshal.PtrToStructure(new IntPtr(buffer.ToInt32()+index), typeof(TTPOLYGONHEADER));

                                int startX = header.pfxStart.x.value;
                                int startY = -header.pfxStart.y.value;

                                // ...do something with start coords...
                                        int endCurvesIndex = index+header.cb;
                                index+=polygonHeaderSize;

                                while(index < endCurvesIndex)
                                {
                                    TTPOLYCURVEHEADER curveHeader = (TTPOLYCURVEHEADER)Marshal.PtrToStructure(new IntPtr(buffer.ToInt32()+index), typeof(TTPOLYCURVEHEADER));
                                    index+=curveHeaderSize;

                                    POINTFX[] curvePoints = new POINTFX[curveHeader.cpfx];

                                    for(int i = 0; i < curveHeader.cpfx; i++)
                                    {
                                        curvePoints[i] = (POINTFX)Marshal.PtrToStructure(new IntPtr(buffer.ToInt32()+index), typeof(POINTFX));
                                        index+=pointFxSize;
                                    }

                                    if(curveHeader.wType == (int)1)
                                    {
                                        // POLYLINE
                                        for(int i=0; i < curveHeader.cpfx; i++)
                                        {
                                            short x = curvePoints[i].x.value;
                                            short y = (short)-curvePoints[i].y.value;

    // ...do something with line points...

                                                                                }
                                    }
                                    else
                                    {
                                        // CURVE
                                        for(int i=0; i < curveHeader.cpfx - 1; i++)
                                        {
                                            POINTFX pfxB = curvePoints[i];
                                            POINTFX pfxC = curvePoints[i+1];

                                            short cx = pfxB.x.value;
                                            short cy = (short)-pfxB.y.value;

                                            short ax;
                                            short ay;

                                            if(i < curveHeader.cpfx - 2)
                                            {
                                                ax = (short)((pfxB.x.value+pfxC.x.value) / 2);
                                                ay = (short)-((pfxB.y.value+pfxC.y.value) / 2);
                                            }
                                            else
                                            {
                                                ax = pfxC.x.value;
                                                ay = (short)-pfxC.y.value;
                                            } // ...do something with curve points...

                                                                                }
                                    }
                                }                                
                            }
                        }
                        else
                        {
                            throw new Exception("Could not retrieve glyph (GDI Error: 0x"+ret.ToString("X")+")");
                        }

                        g.ReleaseHdc(hdc);
                    }
                    finally
                    {                        
                        Marshal.FreeHGlobal(buffer);                    
                    }

                }
            }
            return shape;
        }

Alternative Managed API:

Do you know one? Please contribute it!

Documentation

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Edit This Page
Find References
Show Printable Version
Revisions