README revision 1df6105803c4c56c020a56301c7c9c4890fd4158
97a9a944b5887e91042b019776c41d5dd74557aferikabelelibUEMF is a portable C99 implementation for reading/writing Enhanced Metafile (EMF)
a945f35eff8b6a88009ce73de6d4c862ce58de3csliveand Windows Metafile (WMF) files. libUEMF avoids collisions with with Microsoft defined
a945f35eff8b6a88009ce73de6d4c862ce58de3cslivefunctions and values, so portable programs which use it, and have a Windows version, do
a945f35eff8b6a88009ce73de6d4c862ce58de3cslivenot require any conditional logic to separate the native GDI support from the WMF/EMF support
b686b6a420bde7f78c416b90be11db94cb789979ndproviced by libUEMF. To accomplish this libUEMF does not implement GDI calls. Instead,
b686b6a420bde7f78c416b90be11db94cb789979ndfor each WMR/EMR record type, and each object type incorporated into such a record, it provides
b686b6a420bde7f78c416b90be11db94cb789979ndcorresponding *_set, *_print, and *_swap functions. (For WMF there are also *_get functions, see below.)
b686b6a420bde7f78c416b90be11db94cb789979ndFor example, for the U_EMRBITBLT record there are corresponding functions:
b686b6a420bde7f78c416b90be11db94cb789979ndU_EMRBITBLT_set, U_EMRBITBLT_print, and U_EMRBITBLT_swap. A few additional functions are provided for
b686b6a420bde7f78c416b90be11db94cb789979ndassembling the EMF in memory, debugging, and converting the EMF file to/from Little Endian representation.
b686b6a420bde7f78c416b90be11db94cb789979nd(EMF files' internal data representation is always Little Endian.)
b686b6a420bde7f78c416b90be11db94cb789979ndThis code has been tested on 32 bit Ubuntu (LE), 32 bit Mingw, 64 bit Manriva, and 64 bit Solaris (BE).
b686b6a420bde7f78c416b90be11db94cb789979ndlibUEMF is released under the GPL 2 license, read the file 'COPYING' for more information
b686b6a420bde7f78c416b90be11db94cb789979ndVersion 0.1.10, released January 15, 2014.
b686b6a420bde7f78c416b90be11db94cb789979ndTo report bugs or provide feedback send email to David Mathog, mathog@caltech.edu.
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd--------------------------------------------------------------------------------------------
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0ndEMF file Record structure information has been derived from Mingw, Wine, and libEMF
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0ndheader files, and from Microsoft's EMF Information pdf, release date March 28,2012,
3b3b7fc78d1f5bfc2769903375050048ff41ff26ndlink from here:
b686b6a420bde7f78c416b90be11db94cb789979ndIf the direct link fails the document may be found
9e8d9311a964a8ba9ef5694a369b61b2d4c8c041sliveby searching the web for: "[MS-EMF]: Enhanced Metafile Format".
b686b6a420bde7f78c416b90be11db94cb789979ndWMF file Record structure information is from some of the same sources, as well as:
06ba4a61654b3763ad65f52283832ebf058fdf1csliveIf the direct link fails the document may be found
b686b6a420bde7f78c416b90be11db94cb789979ndby searching the web for: "[MS-WMF]: Windows Metafile Format"
b686b6a420bde7f78c416b90be11db94cb789979ndEMF+ file Record structure is from many helpful responses from Microsoft documentation support
b686b6a420bde7f78c416b90be11db94cb789979ndIf the direct link fails the document may be found
b686b6a420bde7f78c416b90be11db94cb789979ndby searching the web for: "[MS-EMFPLUS]: Enhanced Metafile Format Plus Extensions"
b686b6a420bde7f78c416b90be11db94cb789979ndREADME This file.
b686b6a420bde7f78c416b90be11db94cb789979ndCOPYING GPL V2 license file.
c3a3c963ad3f5b4d816b66117406d4e793049119sliveDOXYFILE Doxygen configuration file, for generating documentation from the source files.
c3a3c963ad3f5b4d816b66117406d4e793049119slivetestbuild.sh Small bash script to build all programs. Modify as needed for target platform.
c3a3c963ad3f5b4d816b66117406d4e793049119slivetestit.sh Small bash script that generates all test files and compares
c3a3c963ad3f5b4d816b66117406d4e793049119slive them with referencess supplied. This script should be edited
20e951959be9ae3d183d42bfce4d8a35b8efc154jim to match your test system before it is run!
3b58542e01ec69422f3086db5825a12fc77b726enduemf.c Contains the *_set functions needed to construct an EMF file.
3b58542e01ec69422f3086db5825a12fc77b726end Also contains auxilliary functions for debugging and constructing
3b58542e01ec69422f3086db5825a12fc77b726end EMF files in memory.
06ba4a61654b3763ad65f52283832ebf058fdf1csliveuemf.h Definitions and structures for EMF records and objects.
3b58542e01ec69422f3086db5825a12fc77b726end Prototypes for *_set and construction functions.
b686b6a420bde7f78c416b90be11db94cb789979nduemf_print.c Contains the *_print functions needed to print the contents of EMF records and objects.
69d3d5f6232f961fd77392db8a975a346fd9cff6nduemf_print.h Prototypes for *_print functions.
3e78df7c8027de6e02326dff46742413de0bfc03coveneruemf_endian.c Contains the *_swap functions needed to rearrange bytes between Big and Little Endian.
3e78df7c8027de6e02326dff46742413de0bfc03covener U_emf_endian() is the only function here that user could should call.
69d3d5f6232f961fd77392db8a975a346fd9cff6nduemf_endian.h Prototype for U_emf_endian() and definitions for Endian type of the local machine.
69d3d5f6232f961fd77392db8a975a346fd9cff6ndupmf.c Contains the *_set and *_get functions needed to construct or read an EMF+ file.
69d3d5f6232f961fd77392db8a975a346fd9cff6nd Also contains auxilliary functions for debugging and constructing
69d3d5f6232f961fd77392db8a975a346fd9cff6nd EMF+ files in memory.
69d3d5f6232f961fd77392db8a975a346fd9cff6ndupmf.h Definitions and structures for EMF+ records and objects.
69d3d5f6232f961fd77392db8a975a346fd9cff6nd Prototypes for *_set, *_get and construction functions.
69d3d5f6232f961fd77392db8a975a346fd9cff6ndupmf_print.c Contains the *_print functions needed to print the contents of EMF+ records and objects.
69d3d5f6232f961fd77392db8a975a346fd9cff6ndupmf_print.h Prototypes for *_print functions.
69d3d5f6232f961fd77392db8a975a346fd9cff6nduwmf.c Contains the *_set and *_get functions needed to construct or read a WMF file.
b686b6a420bde7f78c416b90be11db94cb789979nd Also contains auxilliary functions for debugging and constructing
06ba4a61654b3763ad65f52283832ebf058fdf1cslive WMF files in memory.
3b58542e01ec69422f3086db5825a12fc77b726enduwmf.h Definitions and structures for WMF records and objects.
3b58542e01ec69422f3086db5825a12fc77b726end Prototypes for *_set, *_get and construction functions.
3b58542e01ec69422f3086db5825a12fc77b726enduwmf_print.c Contains the *_print functions needed to print the contents of WMF records and objects.
3b58542e01ec69422f3086db5825a12fc77b726enduwmf_print.h Prototypes for *_print functions.
06ba4a61654b3763ad65f52283832ebf058fdf1csliveuwmf_endian.c Contains the *_swap functions needed to rearrange bytes between Big and Little Endian.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive U_wmf_endian() is the only function here that user could should call.
3b58542e01ec69422f3086db5825a12fc77b726enduwmf_endian.h Prototype for U_wmf_endian() and definitions for Endian type of the local machine.
3b58542e01ec69422f3086db5825a12fc77b726endtestbed_emf.c Program used for testing emf functions in libUEMF. Run it like: testbed_emf flags.
3b58542e01ec69422f3086db5825a12fc77b726end Run with no argument to see what the bit flag values are.
3b58542e01ec69422f3086db5825a12fc77b726end It creates a test file "test_libuemf.emf" which should be identical to
3b58542e01ec69422f3086db5825a12fc77b726end test_libuemf_ref.emf. (This file cannot be imported from EMF into PowerPoint
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd because it contains dotted lines. Use "testbed_emf 1" to generate a file without
3b58542e01ec69422f3086db5825a12fc77b726end any dotted lines. )
3b58542e01ec69422f3086db5825a12fc77b726endtestbed_pmf.c Program used for testing EMF+ functions in libUEMF. Similar to testbed_emf.
3b58542e01ec69422f3086db5825a12fc77b726endtestbed_wmf.c Program used for testing wmf functions in libUEMF. Similar to testbed_emf.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive Program used for testing emf functions in libUEMF. Generates one test file
06ba4a61654b3763ad65f52283832ebf058fdf1cslive in each MAPMODE, MM_TEXT through MM_ANISOTROPIC, optionally with offsets to the
3b58542e01ec69422f3086db5825a12fc77b726end bounds and with particular Viewport origin. (Bounds offset + Viewport Origin
3b58542e01ec69422f3086db5825a12fc77b726end sets the Window origin.)
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Program used for testing wmf functions in libUEMF. Similar to test_mapmodes_emf.
3b58542e01ec69422f3086db5825a12fc77b726endreademf.c Utility that that reads an EMF file and emits its contents in text form.
3b58542e01ec69422f3086db5825a12fc77b726end Also processes EMF+ files.
3b58542e01ec69422f3086db5825a12fc77b726end Run it like: reademf target_file.emf
3b58542e01ec69422f3086db5825a12fc77b726endreadwmf.c Utility that that reads an WMF file and emits its contents in text form.
3b58542e01ec69422f3086db5825a12fc77b726end Run it like: reademf target_file.wmf
3b58542e01ec69422f3086db5825a12fc77b726endcutemf.c Utility for removing specific records from an EMF file.
3b58542e01ec69422f3086db5825a12fc77b726end Run it like: cutemf '2,10,12...13' src_file.emf dst_file.emf
3b58542e01ec69422f3086db5825a12fc77b726endpmfdual2single.c Utility for reducing dual-mode EMF+ file to single mode. Removes all
3b58542e01ec69422f3086db5825a12fc77b726end nonessential EMF records.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Run it like: pmfdual2single dual_mode.emf single_mode.emf
3b58542e01ec69422f3086db5825a12fc77b726end Example output from: testbed_emf 0
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example output from: testbed_pmf 0
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example output from: testbed_emf 4
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example output from: testbed_wmf 0
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example output from: reademf test_libuemf_ref.emf
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example output from: readwmf test_libuemf_ref.wmf
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdtest_mm_<modes>_ref.emf
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example output from: test_mapmodes_emf -vX 2000 -vY 1000
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Example code from Inkscape demonstrate how to integrate libUEMF with another program.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd--------------------------------------------------------------------------------------------
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisdHow to Build:
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdIn Linux/Unix like environments (omit -g flag for production versions):
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Build and install a shared library (example, details may vary) and then build and link
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd the example programs to the shared library:
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uemf.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uemf_print.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uemf_endian.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uemf_utf.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uwmf.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uwmf_print.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c uwmf_endian.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c upmf.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -fPIC -g -c upmf_print.c
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -shared -Wl,-soname,libuemf.so.0 \
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd -o libuemf.so.0.0.3 uemf.o uemf_utf.o uemf_print.o uemf_endian.o uwmf.o uwmf_print.o uwmf_endian.o upmf.o upmf_print.o -lc
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o cutemf cutemf.c -luemf -lm
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o pmfdual2single pmfdual2single.c -luemf -lm
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o reademf reademf.c -luemf -lm
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o readwmf readwmf.c -luemf -lm
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o testbed_emf testbed_emf.c -luemf -lm
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o testbed_emf testbed_wmf.c -luemf -lm
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc -std=c99 -pedantic -Wall -g -o test_mapmodes_emf test_mapmodes_emf.c -luemf -lm
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim For simple development work just build the example programs statically linked:
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim gcc -std=c99 -pedantic -Wall -g -o cutemf cutemf.c uemf.c uemf_endian.c uemf_utf.c -lm
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim gcc -std=c99 -pedantic -Wall -g -o pmfdual2single pmfdual2single.c uemf.c uemf_endian.c uemf_utf.c upmf.c -lm
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim gcc -std=c99 -pedantic -Wall -g -o reademf reademf.c uemf.c uemf_endian.c uemf_utf.c uemf_print.c upmf.c upmf_print.c -lm
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim gcc -std=c99 -pedantic -Wall -g -o readwmf readwmf.c uemf.c uemf_endian.c uemf_utf.c uemf_print.c uwmf.c uwmf_endian.c uwmf_print.c upmf.c upmf_print.c -lm
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim gcc -std=c99 -pedantic -Wall -g -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_utf.c -lm
06ba4a61654b3763ad65f52283832ebf058fdf1cslive gcc -std=c99 -pedantic -Wall -g -o testbed_pmf testbed_pmf.c uemf.c uemf_endian.c uemf_utf.c upmf.c upmf.h -lm
b686b6a420bde7f78c416b90be11db94cb789979nd gcc -std=c99 -pedantic -Wall -g -o testbed_wmf testbed_wmf.c uemf.c uemf_endian.c uemf_utf.c uwmf.c uwmf_endian.c -lm
b686b6a420bde7f78c416b90be11db94cb789979nd gcc -std=c99 -pedantic -Wall -g -o test_mapmodes_emf test_mapmodes_emf.c uemf.c uemf_endian.c uemf_utf.c -lm
b686b6a420bde7f78c416b90be11db94cb789979ndExtra debugging on linux may be enabled in testbed for use under Valgrind. To build that way do instead:
8de9acdcea53109461287090fe0069a665352833rbowen gcc -std=c99 -pedantic -Wall -g -DU_VALGRIND -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_print.c uemf_utf.c -lm
b686b6a420bde7f78c416b90be11db94cb789979ndSparc Solaris 8 and 9 are Big Endian, and to work around some minor incompatibilities with more recent systems,
b686b6a420bde7f78c416b90be11db94cb789979ndassuming gcc is installed in /opt/csw and PATH is set correctly to use it:
b686b6a420bde7f78c416b90be11db94cb789979nd gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o cutemf cutemf.c uemf.c uemf_endian.c uemf_utf.c -lm -L/opt/csw/lib -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o pmfdual2single pmfdual2single.c uemf.c uemf_endian.c uemf_utf.c upmf.c -lm -L/opt/csw/lib -liconv
b686b6a420bde7f78c416b90be11db94cb789979nd gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o reademf reademf.c uemf.c uemf_endian.c uemf_utf.c uemf_print.c upmf.c upmf_print.c -lm -L/opt/csw/lib -liconv
06ba4a61654b3763ad65f52283832ebf058fdf1cslive gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o readwmf readwmf.c uemf.c uemf_endian.c uemf_utf.c uemf_print.c uwmf.c uwmf_endian.c uwmf_print.c upmf.c upmf_print.c -lm -L/opt/csw/lib -liconv
06ba4a61654b3763ad65f52283832ebf058fdf1cslive gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_utf.c -lm -L/opt/csw/lib -liconv
06ba4a61654b3763ad65f52283832ebf058fdf1cslive gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o testbed_pmf testbed_pmf.c uemf.c uemf_endian.c uemf_utf.c upmf.c upmf.h -lm -L/opt/csw/lib -liconv
f55f04901f45165baa5c10f49c35702cb6e5d520nd gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o testbed_wmf testbed_wmf.c uemf.c uemf_endian.c uemf_utf.c uwmf.c uwmf_endian.c -lm -L/opt/csw/lib -liconv
f55f04901f45165baa5c10f49c35702cb6e5d520nd gcc -DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g -o test_mapmodes_emf test_mapmodes_emf.c uemf.c uemf_endian.c uemf_utf.c -lm -L/opt/csw/lib -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener(Note: WORDS_BIGENDIAN would also be produced by autconf's configure, if that was used.)
e0fe7c83f67461f3dc676d90661551edfa111be0covenerDefine WIN32 when compiling for Windows. This uses _wfopen() instead of fopen(), with
e0fe7c83f67461f3dc676d90661551edfa111be0covenerfilename translation from UTF-8 to UTF-16LE. This will allow file opens to utilize unicode
e0fe7c83f67461f3dc676d90661551edfa111be0covenernames. If WIN32 is omitted on Windows file names must be all ASCII. To build on mingw use:
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o cutemf cutemf.c uemf.c uemf_endian.c uemf_utf.c -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o pmfdual2single pmfdual2single.c uemf.c uemf_endian.c uemf_utf.c upmf.c -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o reademf reademf.c uemf.c uemf_endian.c uemf_utf.c uemf_print.c upmf.c upmf_print.c -lm -liconv
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf gcc -DWIN32 -std=c99 -pedantic -Wall -g -o readwmf readwmf.c uemf.c uemf_endian.c uemf_utf.c uemf_print.c uwmf.c uwmf_endian.c uwmf_print.c upmf.c upmf_print.c -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_utf.c -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o testbed_pmf testbed_pmf.c uemf.c uemf_endian.c uemf_utf.c upmf.c upmf.h -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o testbed_wmf testbed_wmf.c uemf.c uemf_endian.c uemf_utf.c uwmf.c uwmf_endian.c -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covener gcc -DWIN32 -std=c99 -pedantic -Wall -g -o test_mapmodes_emf test_mapmodes_emf.c uemf.c uemf_endian.c uemf_utf.c -lm -liconv
e0fe7c83f67461f3dc676d90661551edfa111be0covenerDependencies:
e0fe7c83f67461f3dc676d90661551edfa111be0covener libiconv (if not built into your compiler)
e0fe7c83f67461f3dc676d90661551edfa111be0covener libpng (in the Inkscape examples)
e0fe7c83f67461f3dc676d90661551edfa111be0covener--------------------------------------------------------------------------------------------
e0fe7c83f67461f3dc676d90661551edfa111be0covenerAll modules must also compile without warning under the more restrictive:
e0fe7c83f67461f3dc676d90661551edfa111be0covener ls -1 *.c \
a89e5b3f7630ff342d5e1e9a5d28c07ce1d0029bcovener | extract -fmt 'gcc -Werror=format-security -Wall -Wformat -Wformat-security -W -Wno-pointer-sign -O2 -c -o deleteme.o [1,]' \
e71a4cb937081adb50d5673a1c083a5a7b1a1ab1poirier | execinput
e71a4cb937081adb50d5673a1c083a5a7b1a1ab1poirier--------------------------------------------------------------------------------------------
06ba4a61654b3763ad65f52283832ebf058fdf1csliveUsing libUEMF:
8de9acdcea53109461287090fe0069a665352833rbowenTo write an EMF file the code first runs two initialization functions: emf_start() and htable_create().
8de9acdcea53109461287090fe0069a665352833rbowenThen a U_EMRHEADER record is created. This and all subsequent records are appended to the EMF file in
8de9acdcea53109461287090fe0069a665352833rbowenmemory with emf_append(). Whichever other EMR records are desired are also added. The last EMR record
8de9acdcea53109461287090fe0069a665352833rbowenadded must be the single instance of U_EMREOF. Then the code calls emf_finish(), emf_free(), and
8de9acdcea53109461287090fe0069a665352833rbowenhtable_free(). Conversion of byte order on Big Endian machines to Little Endian is carried out
8de9acdcea53109461287090fe0069a665352833rbowenautomatically in emf_finish(), if it is required.
3b58542e01ec69422f3086db5825a12fc77b726endTo input an EMF file it is is opened and the data read into a buffer in memory with emf_readdata(). On a
3b58542e01ec69422f3086db5825a12fc77b726endBig Endian machine this will also swap machine dependent byte orders as needed. At that point end user code
3b58542e01ec69422f3086db5825a12fc77b726endgenerally has to do something with the data in each record. The simplest case is to just print it, as shown
3b58542e01ec69422f3086db5825a12fc77b726endin reademf.c. More typically it must map the operations into its own graphics model, as shown in the
3b58542e01ec69422f3086db5825a12fc77b726endemf32*.*.example files from Inkscape. Basically the processing program needs to enter a loop, processing
3b58542e01ec69422f3086db5825a12fc77b726endone record at a time, pulling the record size and type from the first two uint32_t values present in each
8de9acdcea53109461287090fe0069a665352833rbowenrecord. It then enters a switch statement with one case for each EMR record type. Each case: statement
8de9acdcea53109461287090fe0069a665352833rbowenwill generally define a pointer to that type of data object. Accessing the data from that pointer is
8de9acdcea53109461287090fe0069a665352833rbowenillustrated in the code for the corresponding *_print function.
8de9acdcea53109461287090fe0069a665352833rbowenWhile libUEMF implements _print and _swap functions for all supported EMR records, end user code would
8de9acdcea53109461287090fe0069a665352833rbowennever call any of these directly. Instead it should either pass a single EMR record
8de9acdcea53109461287090fe0069a665352833rbowento U_emf_onerec_print() (see reademf.c) or the entire completed EMF file in memory buffer to U_emf_endian()
8de9acdcea53109461287090fe0069a665352833rbowenWMF support is similar, except the functions are wmf_start(), wmf_readdata(), and so forth. It is a good
8de9acdcea53109461287090fe0069a665352833rbowenidea to separate end user WMF and EMF generating code into different modules, in order to avoid accidentally
8de9acdcea53109461287090fe0069a665352833rbowenwriting EMR records to a WMF file and vice versa. WHile EMF objects are aligned in memory and so may be
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdaccessed using the supplied structs, the ones for WMF files are not usually aligned and so must be accessed
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdusing the supplied *_get functions. (The difference may not be evident on an x86 platform, but on RISC directly
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdtrying to access objects in memory will result in access violations.)
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdThings to be aware of in EMF files:
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdThe usual idea when employing a graphics file type like EMF is to copy a description of the objects in a
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisddrawing from one program to another. Many of the record types in an EMF file can be thought of as objects,
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdthey are lines or shapes or bitmaps or text. However, Microsoft's GDI implements binary and ternary raster
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdoperations (see the descriptions in uemf.h) and most of these operations are not object like, instead they
8de9acdcea53109461287090fe0069a665352833rbowencombine things on the drawing surface. (There is in each case a copy operation which is object like.)
8de9acdcea53109461287090fe0069a665352833rbowenConsequently, EMF files which use these other raster operations are not particularly easy to import as
8de9acdcea53109461287090fe0069a665352833rbowengraphic objects. For instance, when PowerPoint rotates an image and saves it in an EMF the result is not
3b58542e01ec69422f3086db5825a12fc77b726enda single rotated image object. Instead there is an image containing the rotated image, which is followed by
3b58542e01ec69422f3086db5825a12fc77b726endmasking operations to make the regions outside of the image transparent. There appears to be no standard
3b58542e01ec69422f3086db5825a12fc77b726endfor when and where these subsequent operations will be applied. That is, there is no equivalent of
3b58542e01ec69422f3086db5825a12fc77b726end"begin path" and "end path" to delineate the start and end of such a compound operation. So a program
9744ea3da59d6e7b787c47853db57c324414a9edndreading such a file has no easy way of figuring out which previous object is being modified by a subsequent
2704de98885368683621b01c8f8f4e4b01557611takashiraster operation. The testbed program provided in this package generates a region which applies all
3b58542e01ec69422f3086db5825a12fc77b726endbinary raster operations in vertical slices to two images. The expected result appears in Windows "Preview",
3b58542e01ec69422f3086db5825a12fc77b726endbut if that region is imported into PowerPoint and converted to objects within that program the result looks
06ba4a61654b3763ad65f52283832ebf058fdf1cslivenothing like what Preview shows.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdSupport for U_EMREXTTEXTOUTW is much more common than for U_EMRSMALLTEXT. The latter is easier to use,
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdsince it does not require a Dx array for each text string, but the objects will not import into PowerPoint,
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdfor instance.
3b58542e01ec69422f3086db5825a12fc77b726endThere are two types of dotted/dashed lines. The first uses a set of predefined flags to set the pattern
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdand the latter is end user user defined. Both are restricted to lines of width 1. These built in types are
e71a4cb937081adb50d5673a1c083a5a7b1a1ab1poirierproblematic as key applications cannot handle them properly. PowerPoint cannot convert either type to its
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdinternal object format. The first form loses the pattern and comes through as solid lines. The second type
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdis toxic - even a single dotted line of the second type will prevent the entire EMF from being converted.
3b58542e01ec69422f3086db5825a12fc77b726endThe safest choice is to avoid these patterned line styles entirely. Convert all dots and dashes to separate
3b58542e01ec69422f3086db5825a12fc77b726endline draws before writing those into the EMF file. libUEMF has no problem reading these records, so code
3b58542e01ec69422f3086db5825a12fc77b726endshould accept them for input.
9744ea3da59d6e7b787c47853db57c324414a9edndAs with most graphics file formats there is no single object representation of a complex text string (varying
9744ea3da59d6e7b787c47853db57c324414a9edndfont size, super/sub script, bold, italic,.etc.). Such text must be decomposed into multiple text strings,
9744ea3da59d6e7b787c47853db57c324414a9edndeach with its own formatting. It is unlikely that a subsequent program reading these records from the EMF
9744ea3da59d6e7b787c47853db57c324414a9edndwill be able to reassemble them back into a single complex text string.
3b58542e01ec69422f3086db5825a12fc77b726endIf a font used in an EMF file is not present on both the sending and receiving systems text will not look the
3b58542e01ec69422f3086db5825a12fc77b726endsame on both. Font substitution is usually silent in most programs, so it may not be evident why the text looks
9744ea3da59d6e7b787c47853db57c324414a9ednda little odd. However, if text is simple, that is, consists of just one line of text without size, color,
3b58542e01ec69422f3086db5825a12fc77b726endor other changes, then it will look approximately correct after font substitution.
f34ee9017606cf677db8c6dc37cb60b3a0c5f6a1poirierThings to be aware of in WMF files:
1ad1c5f9a82d056966dcca9c6108c5ace8eed446rbowenWMF graphics are quite limited when compared to EMF graphics. When reading a WMF file it is essential that
3b58542e01ec69422f3086db5825a12fc77b726endend user code always create a specified object, even if that object is just a placeholder with no real
1ad1c5f9a82d056966dcca9c6108c5ace8eed446rbowenfunction. If any "create" operation presented by the WMF file is not handled then the object indices used
1ad1c5f9a82d056966dcca9c6108c5ace8eed446rbowenfurther along in the WMF file will be off, with very bad results! WMF "regions" are not supported by libUEMF,
da57d338b0977cbdc021606d3230194a8ad4a56cndhowever, if an operation creates regions, this type of placeholder must still be created.
9744ea3da59d6e7b787c47853db57c324414a9edndIn theory WMF supports mapmodes other than Anisotropic. However, since many programs do not handle
06ba4a61654b3763ad65f52283832ebf058fdf1cslivethese other modes it is strongly suggested that any WMF files generated use Anisotropic. For this
da57d338b0977cbdc021606d3230194a8ad4a56cndreason there is no test_mapmodes_wmf program - windows XP preview did not show anything when WMF
da57d338b0977cbdc021606d3230194a8ad4a56cndfiles in the other modes were produced. With no positive control there was no way to verify that they
da57d338b0977cbdc021606d3230194a8ad4a56cndwere valid.
da57d338b0977cbdc021606d3230194a8ad4a56cndThings to be aware of in EMF+ files:
da57d338b0977cbdc021606d3230194a8ad4a56cndEMF+ files are usually stored in files with an ".emf" file extension. In this package EMF+ programs,
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisdfunctions, and definitions use PMF or PMR to distinguish them from the EMF and WMF material. ("EMF+"
da57d338b0977cbdc021606d3230194a8ad4a56cndis not an allowed variable or function name in C.) Dual mode EMF+ files contain both EMF and
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisdEMF+ records. HOWEVER, those generated by PowerPoint are defective in that they drop all text
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisdinformation from the drawing in the EMF+ representation. There is no simple way to line up the
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisdEMF and EMF+ records in their representations to determine which ones correspond to which drawing
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisdobject. So it is generally not possible to see which elements are represented in both
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimrepresentations, or which are missing in one representation. The example file generated by this library
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimhas only EMF+ records plus the few EMF records needed to wrap them.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimText in EMF+ is placed not from the baseline, as in EMF, but from the upper left corner of the Em square.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimUse the utility function U_PMR_drawstring() to draw text onto a baseline. Font
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimsubstitutions result in badly placed text because even fonts that look similar on the screen may have
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimdifferent font metrics. Specifically, font substitutions look worse in EMF+ files than they do
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimin EMF files. There is no way to embed fonts, or their font information in the EMF+ file.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimConsequently the text representation within an EMF+ file is not very portable between systems - it will
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimonly render correctly if the second system has all of the fonts used in the document. The testbed_pmf.c
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimprogram contains some metrics for common fonts which may be used with U_PMR_drawstring()
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jimto accurately place text.
69d3d5f6232f961fd77392db8a975a346fd9cff6nd--------------------------------------------------------------------------------------------
3b58542e01ec69422f3086db5825a12fc77b726end (Note, version numbers in files represent the libUEMF release where it was last modified, so not
dd2f29c187db35e7635ce67a83dddceb75be87a4minfrin all files will show the same version numbers in each release.)
b686b6a420bde7f78c416b90be11db94cb789979nd0.1.10 2014-01-14
b686b6a420bde7f78c416b90be11db94cb789979nd Slight changes in documentation for uemf.h.
b686b6a420bde7f78c416b90be11db94cb789979nd Fixed typo in uemf_endian.c.
b686b6a420bde7f78c416b90be11db94cb789979nd Fixed a tiny bug in uemf.c (if memory allocation failed a struct would have
b686b6a420bde7f78c416b90be11db94cb789979nd been deleted before the struct itself.
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd0.1.9 2013-12-02
b686b6a420bde7f78c416b90be11db94cb789979nd Added U_PMF_DASHEDLINEDATA_set3 (dot/dash pattern from bits in a uint32_t).
b686b6a420bde7f78c416b90be11db94cb789979nd Finally was able to make linear gradient gradientfill records work. Updated
b686b6a420bde7f78c416b90be11db94cb789979nd testbed_emf.c to include that.
b686b6a420bde7f78c416b90be11db94cb789979nd0.1.8 2013-11-28
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd Fixed a bug in U_PMF_REGIONNODEPATH_print(), returned size was 4 too small.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive Changed formatting of U_PMF_REGIONNODECHILDNODES_print() output to improve readability
06ba4a61654b3763ad65f52283832ebf058fdf1cslive of nested region structures in reademf.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive0.1.7 2013-11-20
06ba4a61654b3763ad65f52283832ebf058fdf1cslive Added EMF+ support.
3b58542e01ec69422f3086db5825a12fc77b726end Converted U_RGA and similar from defines to functions, because the method being used
8de9acdcea53109461287090fe0069a665352833rbowen in the define (from C99) was not exactly compatible with C++ compilation.
8de9acdcea53109461287090fe0069a665352833rbowen Fixed error in test_mapmodes_emf.c where truncation float to integer was used where round
8de9acdcea53109461287090fe0069a665352833rbowen have been, resulting in an off by 1 error on some platforms.
8de9acdcea53109461287090fe0069a665352833rbowen Eliminated PU_W* pointers.
8de9acdcea53109461287090fe0069a665352833rbowen Cleaned up Doxygen comments.
8de9acdcea53109461287090fe0069a665352833rbowen0.1.6. 2013-04-18
3b58542e01ec69422f3086db5825a12fc77b726end Added tests which vary background mode, background color, and text color.
3b58542e01ec69422f3086db5825a12fc77b726end Slight modification to testit.sh.
3b58542e01ec69422f3086db5825a12fc77b726end Updated example files.
3b58542e01ec69422f3086db5825a12fc77b726end0.1.5. 2013-02-13
3b58542e01ec69422f3086db5825a12fc77b726end Added missing parameter for WMF RESTOREDC_set/get.
3b58542e01ec69422f3086db5825a12fc77b726end Replaced all sizeof() in uwmf.c that referred to UWMF structures with their
3b58542e01ec69422f3086db5825a12fc77b726end U_SIZE_* equivalents.
8de9acdcea53109461287090fe0069a665352833rbowen Added DIB related WMF _get functions. (Which were missing). These are U_BITMAPCOREHEADER_get,
3a6ae8b015850ba60719ed97ae549e27eee84f0drbowen U_BITMAPINFOHEADER_get, wget_dib_params
8de9acdcea53109461287090fe0069a665352833rbowen Added const where appropriate to wmf _get functions.
8de9acdcea53109461287090fe0069a665352833rbowen Added comprehensive cap,join,miter tests to testbeds.
8de9acdcea53109461287090fe0069a665352833rbowen Fixed bug in gradient4_swap().
3a6ae8b015850ba60719ed97ae549e27eee84f0drbowen Fixed bug in emr_arc_points_common(), used vector where unit vectors were
3a6ae8b015850ba60719ed97ae549e27eee84f0drbowen needed, sometimes flipped direction for arcs/chords.
3a6ae8b015850ba60719ed97ae549e27eee84f0drbowen Fixed bug in U_WMFTEXTOUT_get().
3a6ae8b015850ba60719ed97ae549e27eee84f0drbowen Changed all dst->Dst and src->Src as call variables in WMF code.
3a6ae8b015850ba60719ed97ae549e27eee84f0drbowen Denigrated htable_*() for emf, these become emf_htable_*(), to match naming convention
8de9acdcea53109461287090fe0069a665352833rbowen used for wmf_table_*().
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd0.1.4 2013-02-04
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Added code to handle DIB formats that use clrUsed=0 to mean "maximum number of color entries",
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd this showed up in several places, including uemf.c and uemf_print.c.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Added some labels to test drawings, slightly rearranged image section, added
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd PNG and JPG image tests and clrUsed=0 images.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Modified uemf_endian.c to suppress some compiler warnings.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Changed get_DIB_params to return the Compression enumeration.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd Fixed a typo in uwmf_print.c.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd0.1.3 2013-01-29 Add modes to EMF test programs that changes worldtransform, so
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd that the resulting test files will exercise rotation transforms.
8de9acdcea53109461287090fe0069a665352833rbowen Added flags indication for testbed programs.
8de9acdcea53109461287090fe0069a665352833rbowen Added test for ROUNDRECT records. Swapped argument orders for those _get/_set operations.
8de9acdcea53109461287090fe0069a665352833rbowen0.1.2 2013-01-25 Fixed bug revealed by newer gcc on Solaris, assignment of aligned 32 bit to unaligned
3b58542e01ec69422f3086db5825a12fc77b726end 16 bit segfaulted.
3b58542e01ec69422f3086db5825a12fc77b726end0.1.1 2013-01-24 Fixed a few compiler warnings under g++, mostly having to do
3b58542e01ec69422f3086db5825a12fc77b726end with signed unsigned comparisons. Eliminated
9744ea3da59d6e7b787c47853db57c324414a9ednd an unused variable from wmf_finish and two stray lines from U_WMRHEADER_set.
9744ea3da59d6e7b787c47853db57c324414a9ednd Cleaned up doxygen comments.
2704de98885368683621b01c8f8f4e4b01557611takashi0.1.0 2013-01-09 Added WMF functions.
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd Simplified print functions. Changed output format of reademf slightly,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive from U_EMRXXX to U_EMR_XXX - easier to read the new way.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive0.0.11 2012-12-04 Moved UTF and related functions out of uemf.c uemf.h and into uemf_utf.c uemf_utf.h.
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd0.0.10 2012-11-28 Discovered that not enough space was being allocated for some UTF conversions. To be
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd safe need 4 bytes per glyph + 1 for UTF-8.
3b58542e01ec69422f3086db5825a12fc77b726end0.0.9 2012-09-26 Some "uninitialized variable warnings" for certain versions of
8eb7c1fd1d6abcf2529dcb265573b194aba56794chrisd gcc. These were, as far as I could tell, all spurious, but to quiet them
9744ea3da59d6e7b787c47853db57c324414a9ednd the variables in question were all initialized to 0.
9744ea3da59d6e7b787c47853db57c324414a9ednd Fixed header related print/swap functions - depending on what type of header there
9744ea3da59d6e7b787c47853db57c324414a9ednd could be an access violation.
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd Fixed U_Utf16leToUtf8, could leak memory if the conversion failed.
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd Fixed sections which were not testing for all types of EMF headers.
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd Added RGBA_to_RGBA() so that extractions of subsets of bitmaps (offset, different size)
4c881d2fffa365e2e0c5e25eb1cf77f4f9406e44chrisd can be handled.
9744ea3da59d6e7b787c47853db57c324414a9ednd Added cutemf. Utility to remove records from an EMF file.
9744ea3da59d6e7b787c47853db57c324414a9ednd Added test_mapmodes. Program to generate test files in each MAPMODE.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim Added test_mm_(mode)_ref.emf files. These are reference for:
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim test_mapmodes -vX 2000 -vY 1000
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim0.0.8 2012-09-10 Fixed bug in htable_insert, failed to celear newly added table
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim slots. Fixed test for EMR_GRADIENTFILL triangle mode (rectangle still produces toxic EMF files.)
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim Fixed bug in gradientfill_swap on Solaris.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim0.0.7 2012-08-30 Added/fixed tests for hatched, DIB, and mono strokes.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim Corrected error in U_EMREXTCREATEPEN_set.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim0.0.6 2012-08-21 Added/fixed tests for hatched, DIB, and mono fills.
cb87a91abb4084fe5fa5a53047aeb6dcf9094115jim0.0.5 2012-08-08 Minor changes to uemf.c to suppress compiler warnings. Fixed
4ae7c4126530196ebe64b20b21ed476850d509d4nd one bug in SET_CB_FROM_PXBMI macro (which was not triggered in testbed
69d3d5f6232f961fd77392db8a975a346fd9cff6nd because all images were the same size).
06ba4a61654b3763ad65f52283832ebf058fdf1cslive0.0.4 2012-07-25 More tests in testbed.c. Found and fixed bugs in
06ba4a61654b3763ad65f52283832ebf058fdf1cslive U_POLYPOLYLINE and U_POLYPOLYGON related code.
b686b6a420bde7f78c416b90be11db94cb789979nd0.0.3 2012-07-24 Warnings related to printing size_t on 64 bit Linux. Correct
b686b6a420bde7f78c416b90be11db94cb789979nd fix is to use "zd", but gcc -std=c99 does not support that on Solaris 9,
b686b6a420bde7f78c416b90be11db94cb789979nd the only available big endian system. So use cast or the size_t to (int)
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd and stick with %d format specifier. This should be OK as the sizes involved
4aa805f8500255bc52a4c03259fe46df10a1d07cyoshiki should not be all that large.
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd Bug in core9 affecting U_EMRARC_swap(), and related, on Big Endian.
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd0.0.2 2012-07-12 first release