EMF  1.0
libEMF: Enhanced Metafile Library

Table of Contents


libEMF is a C/C++ library which provides a drawing toolkit based on ECMA-234. The general purpose of this library is to create vector graphics files on POSIX systems which can be imported into OpenOffice.org or LibreOffice. Times have changed, though. These days, you can import SVGs, or even PDFs, into OpenOffice or LibreOffice. Those are much better choices than EMF files.

My general interest in this library is for making scientific plots with gnuplot and Grace(forthcoming). Therefore, this software includes patches to those programs to add the EMF as an output option. This library is mostly limited to the graphics commands required for gnuplot and Grace output drivers, though it's trivial to add new ones.

It is also possible now to generate EMF files from PSTOEDIT on POSIX systems. Therefore, if your graphics code only outputs PostScript, you can now easily convert it to EMF.

libEMF is hosted on SourceForge. If you have questions or comments, try out the libEMF mailing list.


libEMF uses a standard autoconf-generated configure script to prepare it for compilation. If you want to activate printing of EMF records, run the configure script with:

./configure --enable-editing

A single program is provided which can print the complete contents of a metafie (as far as the library understands them, anyway),

printemf metafile.emf


The documentation of this project is generated with Doxygen and is largely for the internals of the library. However, the graphics commands which are available from C are given here.


You will probably only use libEMF in the context of an output driver for another graphics program, but should you want to do some custom graphics generation, here is an annotated example.

#include <emf.h> // Will depend on your installation of libEMF

int main ( int argc, char* argv[] )

The first step is to create a device context for the metafile. The usual way this is accomplished is by acquiring a copy of the "desktop" device context and using it as a starting point for the metafile device context. libEMF supports the commands GetDesktopWindow() and GetDC(), but they are just dummy functions. The metafile device context has its own internal definitions.

The metafile creation subroutine takes four arguments (the first of which, the reference device context as obtained above, is ignored). The second argument is the path name of the metafile; you can use whatever name is valid on the system, but SO/OO.org prefers the file to end with the .emf extension. The third argument gives the size and position of the metafile; since SO/OO.org ignores the position, the first two values should be zero; the second pair of values should give the desired physical width and height of the drawing in units of 1/1000-th centimeters. The last argument to the creation routine is the description of the metafile; by convention, this consists of two null-terminated strings with an extra '\0' at the end.

   HWND desktop = GetDesktopWindow();
   HDC dc = GetDC( desktop );

   RECT size = { 0, 0, 10000, 10000 }; // 10cm x 10cm
   PCSTR filename = "example.emf";
   PCSTR description = "Example metafile created\0with libEMF\0";

   HDC metaDC = CreateEnhMetaFile( 0, filename, &size, description );

Next, we want to set the drawing properties of the pen, brush and font to something other than the default, say a wide, cyan pen and a solid, blue brush, and a bold Helvetica font.

   LOGPEN lpen = { PS_SOLID, {2000,2000}, RGB(0,0xff,0xff) };
   LOGBRUSH lbrush = { BS_SOLID, RGB(0x0,0x0,0xff), HS_HORIZONTAL };
   HPEN pen = CreatePenIndirect( &lpen );
   HBRUSH brush = CreateBrushIndirect( &lbrush );
   HFONT font = CreateFont( -1100, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET,
                      DEFAULT_PITCH | FF_DONTCARE, "Helvetica" );

   // Make these the active objects for their respective types

   SelectObject( metaDC, pen );
   SelectObject( metaDC, brush );
   SelectObject( metaDC, font );

Set the window size to the natural coordinates of the drawing. Here, we want to draw on a 100x100 grid.

   SetWindowExtEx( metaDC, 100, 100, 0 );

Now, we can draw as we like. For example, we'll make a solid background with some text centered in the window.

   Rectangle( metaDC, 0, 0, 100, 100 );

   SetTextColor( metaDC, RGB(0,0xff,0) );
   SetTextAlign( metaDC, TA_CENTER+TA_BASELINE );
   SetBkMode( metaDC, TRANSPARENT );
   TextOutA( metaDC, 50, 50, "Welcome to libEMF", 17 );

Finally, the metafile is written to disk when the metafile is closed. Delete the metafile and its assocated device context to free all the memory they have consumed.

   metafile = CloseEnhMetaFile( metaDC );
   DeleteEnhMetaFile( metafile );
   DeleteDC( metaDC );

   return 0;

This is result of importing example.emf into OO.org and exporting the drawing as a PNG file (after using The GIMP to crop the transparent boundary).



Special thanks to Wolfgang Glunz (wglunz@pstoedit.net) for suggestions and help testing.

Copyright © 2002 lignum Computing, Inc., dallenbarnett@users.sourceforge.net

Hosted by Get ECMA-234 Metafile Library at SourceForge.net. Fast, secure and Free Open Source software downloads